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.

1857 lines
69KB

  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. // TODO
  368. (void)key;
  369. }
  370. void setValue(const QString& key, const uint value)
  371. {
  372. QSafeSettings::setValue(key, value);
  373. }
  374. void setValue(const QString& key, const QPluginInfoList& value)
  375. {
  376. return;
  377. // TODO
  378. (void)key;
  379. (void)value;
  380. }
  381. };
  382. // --------------------------------------------------------------------------------------------------------------------
  383. template <class T> inline T static_cast_void(const void* ptr)
  384. {
  385. return static_cast<T>(ptr);
  386. }
  387. struct PluginInfoBytes {
  388. uint API;
  389. uint build;
  390. CARLA_BACKEND_NAMESPACE::PluginType type;
  391. uint hints;
  392. uint64_t uniqueId;
  393. uint audioIns;
  394. uint audioOuts;
  395. uint cvIns;
  396. uint cvOuts;
  397. uint midiIns;
  398. uint midiOuts;
  399. uint parametersIns;
  400. uint parametersOuts;
  401. };
  402. QVariant asVariant(const PluginInfo& plugin)
  403. {
  404. const PluginInfoBytes data = {
  405. plugin.API,
  406. plugin.build,
  407. plugin.type,
  408. plugin.hints,
  409. plugin.uniqueId,
  410. plugin.audioIns,
  411. plugin.audioOuts,
  412. plugin.cvIns,
  413. plugin.cvOuts,
  414. plugin.midiIns,
  415. plugin.midiOuts,
  416. plugin.parametersIns,
  417. plugin.parametersOuts
  418. };
  419. QByteArray qdata(static_cast_void<const char*>(&data), sizeof(data));
  420. {
  421. const QByteArray qcategory(plugin.category.toUtf8());
  422. qdata += qcategory.constData();
  423. qdata += '\0';
  424. }
  425. {
  426. const QByteArray qfilename(plugin.filename.toUtf8());
  427. qdata += qfilename.constData();
  428. qdata += '\0';
  429. }
  430. {
  431. const QByteArray qname(plugin.name.toUtf8());
  432. qdata += qname.constData();
  433. qdata += '\0';
  434. }
  435. {
  436. const QByteArray qlabel(plugin.label.toUtf8());
  437. qdata += qlabel.constData();
  438. qdata += '\0';
  439. }
  440. {
  441. const QByteArray qmaker(plugin.maker.toUtf8());
  442. qdata += qmaker.constData();
  443. qdata += '\0';
  444. }
  445. QVariant var;
  446. var.setValue(qdata);
  447. return var;
  448. }
  449. PluginInfo asPluginInfo(const QVariant& var)
  450. {
  451. const QByteArray qdata(var.toByteArray());
  452. CARLA_SAFE_ASSERT_RETURN((size_t)qdata.size() >= sizeof(PluginInfoBytes) + sizeof(char)*5, {});
  453. const PluginInfoBytes* const data = static_cast_void<const PluginInfoBytes*>(qdata.constData());
  454. PluginInfo plugin = {
  455. data->API,
  456. data->build,
  457. static_cast<PluginType>(data->type),
  458. data->hints,
  459. {}, {}, {}, {}, {},
  460. data->uniqueId,
  461. data->audioIns,
  462. data->audioOuts,
  463. data->cvIns,
  464. data->cvOuts,
  465. data->midiIns,
  466. data->midiOuts,
  467. data->parametersIns,
  468. data->parametersOuts
  469. };
  470. const char* sdata = static_cast_void<const char*>(data) + sizeof(PluginInfoBytes);
  471. plugin.category = QString::fromUtf8(sdata);
  472. sdata += plugin.category.size() + 1;
  473. plugin.filename = QString::fromUtf8(sdata);
  474. sdata += plugin.filename.size() + 1;
  475. plugin.name = QString::fromUtf8(sdata);
  476. sdata += plugin.name.size() + 1;
  477. plugin.label = QString::fromUtf8(sdata);
  478. sdata += plugin.label.size() + 1;
  479. plugin.maker = QString::fromUtf8(sdata);
  480. sdata += plugin.maker.size() + 1;
  481. return plugin;
  482. }
  483. // --------------------------------------------------------------------------------------------------------------------
  484. // Plugin List Dialog
  485. struct PluginListDialog::Self {
  486. enum TableIndex {
  487. TABLEWIDGET_ITEM_FAVORITE,
  488. TABLEWIDGET_ITEM_NAME,
  489. TABLEWIDGET_ITEM_LABEL,
  490. TABLEWIDGET_ITEM_MAKER,
  491. TABLEWIDGET_ITEM_BINARY,
  492. };
  493. // To be changed by parent
  494. bool hasLoadedLv2Plugins = false;
  495. Ui_PluginListDialog ui;
  496. HostSettings hostSettings = {};
  497. int fLastTableIndex = 0;
  498. PluginInfo fRetPlugin;
  499. QWidget* const fRealParent;
  500. QStringList fFavoritePlugins;
  501. bool fFavoritePluginsChanged = false;
  502. const QString fTrYes;
  503. const QString fTrNo;
  504. const QString fTrNative;
  505. Self(QWidget* const parent)
  506. : fRealParent(parent),
  507. fTrYes(tr("Yes")),
  508. fTrNo(tr("No")),
  509. fTrNative(tr("Native")) {}
  510. static Self& create(QWidget* const parent)
  511. {
  512. Self* const self = new Self(parent);
  513. return *self;
  514. }
  515. inline QString tr(const char* const txt)
  516. {
  517. return fRealParent != nullptr ? fRealParent->tr(txt) : QString::fromUtf8(txt);
  518. }
  519. void createFavoritePluginDict()
  520. {
  521. #if 0
  522. return {
  523. 'name' : plugin['name'],
  524. 'build' : plugin['build'],
  525. 'type' : plugin['type'],
  526. 'filename': plugin['filename'],
  527. 'label' : plugin['label'],
  528. 'uniqueId': plugin['uniqueId'],
  529. }
  530. #endif
  531. }
  532. void checkFilters()
  533. {
  534. const QCarlaString text = ui.lineEdit->text().toLower();
  535. const bool hideEffects = !ui.ch_effects->isChecked();
  536. const bool hideInstruments = !ui.ch_instruments->isChecked();
  537. const bool hideMidi = !ui.ch_midi->isChecked();
  538. const bool hideOther = !ui.ch_other->isChecked();
  539. const bool hideInternal = !ui.ch_internal->isChecked();
  540. const bool hideLadspa = !ui.ch_ladspa->isChecked();
  541. const bool hideDssi = !ui.ch_dssi->isChecked();
  542. const bool hideLV2 = !ui.ch_lv2->isChecked();
  543. const bool hideVST2 = !ui.ch_vst->isChecked();
  544. const bool hideVST3 = !ui.ch_vst3->isChecked();
  545. const bool hideCLAP = !ui.ch_clap->isChecked();
  546. const bool hideAU = !ui.ch_au->isChecked();
  547. const bool hideJSFX = !ui.ch_jsfx->isChecked();
  548. const bool hideKits = !ui.ch_kits->isChecked();
  549. const bool hideNative = !ui.ch_native->isChecked();
  550. const bool hideBridged = !ui.ch_bridged->isChecked();
  551. const bool hideBridgedWine = !ui.ch_bridged_wine->isChecked();
  552. const bool hideNonFavs = ui.ch_favorites->isChecked();
  553. const bool hideNonRtSafe = ui.ch_rtsafe->isChecked();
  554. const bool hideNonCV = ui.ch_cv->isChecked();
  555. const bool hideNonGui = ui.ch_gui->isChecked();
  556. const bool hideNonIDisp = ui.ch_inline_display->isChecked();
  557. const bool hideNonStereo = ui.ch_stereo->isChecked();
  558. #if 0
  559. if HAIKU or LINUX or MACOS:
  560. nativeBins = [BINARY_POSIX32, BINARY_POSIX64]
  561. wineBins = [BINARY_WIN32, BINARY_WIN64]
  562. elif WINDOWS:
  563. nativeBins = [BINARY_WIN32, BINARY_WIN64]
  564. wineBins = []
  565. else:
  566. nativeBins = []
  567. wineBins = []
  568. #endif
  569. ui.tableWidget->setRowCount(fLastTableIndex);
  570. for (int i=0; i<fLastTableIndex; ++i)
  571. {
  572. const PluginInfo plugin = asPluginInfo(ui.tableWidget->item(i, TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+1));
  573. const QString ptext = ui.tableWidget->item(i, TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+2).toString();
  574. const uint aIns = plugin.audioIns;
  575. const uint aOuts = plugin.audioOuts;
  576. const uint cvIns = plugin.cvIns;
  577. const uint cvOuts = plugin.cvOuts;
  578. const uint mIns = plugin.midiIns;
  579. const uint mOuts = plugin.midiOuts;
  580. const uint phints = plugin.hints;
  581. const PluginType ptype = plugin.type;
  582. const QString categ = plugin.category;
  583. const bool isSynth = phints & PLUGIN_IS_SYNTH;
  584. const bool isEffect = aIns > 0 && aOuts > 0 && !isSynth;
  585. const bool isMidi = aIns == 0 && aOuts == 0 && mIns > 0 && mOuts > 0;
  586. const bool isKit = ptype == PLUGIN_SF2 || ptype == PLUGIN_SFZ;
  587. const bool isOther = !(isEffect || isSynth || isMidi || isKit);
  588. const bool isNative = plugin.build == BINARY_NATIVE;
  589. const bool isRtSafe = phints & PLUGIN_IS_RTSAFE;
  590. const bool isStereo = (aIns == 2 && aOuts == 2) || (isSynth && aOuts == 2);
  591. const bool hasCV = cvIns + cvOuts > 0;
  592. const bool hasGui = phints & PLUGIN_HAS_CUSTOM_UI;
  593. const bool hasIDisp = phints & PLUGIN_HAS_INLINE_DISPLAY;
  594. #if 0
  595. const bool isBridged = bool(not isNative and plugin.build in nativeBins);
  596. const bool isBridgedWine = bool(not isNative and plugin.build in wineBins);
  597. #else
  598. const bool isBridged = false;
  599. const bool isBridgedWine = false;
  600. #endif
  601. const auto hasText = [text, ptext]() {
  602. const QStringList textSplit = text.strip().split(' ');
  603. for (const QString& t : textSplit)
  604. if (ptext.contains(t))
  605. return true;
  606. return false;
  607. };
  608. /**/ if (hideEffects && isEffect)
  609. ui.tableWidget->hideRow(i);
  610. else if (hideInstruments && isSynth)
  611. ui.tableWidget->hideRow(i);
  612. else if (hideMidi && isMidi)
  613. ui.tableWidget->hideRow(i);
  614. else if (hideOther && isOther)
  615. ui.tableWidget->hideRow(i);
  616. else if (hideKits && isKit)
  617. ui.tableWidget->hideRow(i);
  618. else if (hideInternal && ptype == PLUGIN_INTERNAL)
  619. ui.tableWidget->hideRow(i);
  620. else if (hideLadspa && ptype == PLUGIN_LADSPA)
  621. ui.tableWidget->hideRow(i);
  622. else if (hideDssi && ptype == PLUGIN_DSSI)
  623. ui.tableWidget->hideRow(i);
  624. else if (hideLV2 && ptype == PLUGIN_LV2)
  625. ui.tableWidget->hideRow(i);
  626. else if (hideVST2 && ptype == PLUGIN_VST2)
  627. ui.tableWidget->hideRow(i);
  628. else if (hideVST3 && ptype == PLUGIN_VST3)
  629. ui.tableWidget->hideRow(i);
  630. else if (hideCLAP && ptype == PLUGIN_CLAP)
  631. ui.tableWidget->hideRow(i);
  632. else if (hideAU && ptype == PLUGIN_AU)
  633. ui.tableWidget->hideRow(i);
  634. else if (hideJSFX && ptype == PLUGIN_JSFX)
  635. ui.tableWidget->hideRow(i);
  636. else if (hideNative && isNative)
  637. ui.tableWidget->hideRow(i);
  638. else if (hideBridged && isBridged)
  639. ui.tableWidget->hideRow(i);
  640. else if (hideBridgedWine && isBridgedWine)
  641. ui.tableWidget->hideRow(i);
  642. else if (hideNonRtSafe && not isRtSafe)
  643. ui.tableWidget->hideRow(i);
  644. else if (hideNonCV && not hasCV)
  645. ui.tableWidget->hideRow(i);
  646. else if (hideNonGui && not hasGui)
  647. ui.tableWidget->hideRow(i);
  648. else if (hideNonIDisp && not hasIDisp)
  649. ui.tableWidget->hideRow(i);
  650. else if (hideNonStereo && not isStereo)
  651. ui.tableWidget->hideRow(i);
  652. else if (text.isNotEmpty() && ! hasText())
  653. ui.tableWidget->hideRow(i);
  654. #if 0
  655. else if (hideNonFavs && _createFavoritePluginDict(plugin) not in fFavoritePlugins)
  656. ui.tableWidget->hideRow(i);
  657. #endif
  658. else if (ui.ch_cat_all->isChecked() or
  659. (ui.ch_cat_delay->isChecked() && categ == "delay") or
  660. (ui.ch_cat_distortion->isChecked() && categ == "distortion") or
  661. (ui.ch_cat_dynamics->isChecked() && categ == "dynamics") or
  662. (ui.ch_cat_eq->isChecked() && categ == "eq") or
  663. (ui.ch_cat_filter->isChecked() && categ == "filter") or
  664. (ui.ch_cat_modulator->isChecked() && categ == "modulator") or
  665. (ui.ch_cat_synth->isChecked() && categ == "synth") or
  666. (ui.ch_cat_utility->isChecked() && categ == "utility") or
  667. (ui.ch_cat_other->isChecked() && categ == "other"))
  668. ui.tableWidget->showRow(i);
  669. else
  670. ui.tableWidget->hideRow(i);
  671. }
  672. }
  673. #ifdef CARLA_FRONTEND_NO_CACHED_PLUGIN_API
  674. void addPluginToTable(const CarlaPluginDiscoveryInfo* const info)
  675. {
  676. carla_stdout("addPluginToTable %p %s", info, info->filename);
  677. ui.tableWidget->setRowCount(fLastTableIndex + 1);
  678. const PluginInfo pinfo = {
  679. PLUGIN_QUERY_API_VERSION,
  680. info->btype,
  681. info->ptype,
  682. info->metadata.hints,
  683. getPluginCategoryAsString(info->metadata.category),
  684. QString::fromUtf8(info->filename),
  685. QString::fromUtf8(info->metadata.name),
  686. QString::fromUtf8(info->label),
  687. QString::fromUtf8(info->metadata.maker),
  688. info->uniqueId,
  689. info->io.audioIns,
  690. info->io.audioOuts,
  691. info->io.cvIns,
  692. info->io.cvOuts,
  693. info->io.midiIns,
  694. info->io.midiOuts,
  695. info->io.parameterIns,
  696. info->io.parameterOuts,
  697. };
  698. const int index = fLastTableIndex;
  699. const bool isFav = false;
  700. QTableWidgetItem* const itemFav = new QTableWidgetItem;
  701. itemFav->setCheckState(isFav ? Qt::Checked : Qt::Unchecked);
  702. itemFav->setText(isFav ? " " : " ");
  703. const QString searchablePluginText = (
  704. QString::fromUtf8(info->label) +
  705. QString::fromUtf8(info->filename) +
  706. QString::fromUtf8(info->metadata.name) +
  707. QString::fromUtf8(info->metadata.maker)).toLower();
  708. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_FAVORITE, itemFav);
  709. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_NAME, new QTableWidgetItem(pinfo.name));
  710. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_LABEL, new QTableWidgetItem(pinfo.label));
  711. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_MAKER, new QTableWidgetItem(pinfo.maker));
  712. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_BINARY,
  713. new QTableWidgetItem(QFileInfo(pinfo.filename).fileName()));
  714. QTableWidgetItem* const itemName = ui.tableWidget->item(index, TABLEWIDGET_ITEM_NAME);
  715. itemName->setData(Qt::UserRole+1, asVariant(pinfo));
  716. itemName->setData(Qt::UserRole+2, searchablePluginText);
  717. fLastTableIndex += 1;
  718. carla_stdout("addPluginToTable %p %s END", info, info->filename);
  719. }
  720. static void _discoveryCallback(void* const ptr, const CarlaPluginDiscoveryInfo* const info)
  721. {
  722. carla_stdout("_discoveryCallback %p %s", info, info->filename);
  723. static_cast<PluginListDialog::Self*>(ptr)->addPluginToTable(info);
  724. }
  725. #else
  726. void addPluginToTable(const PluginInfo& plugin, const PluginType ptype)
  727. {
  728. if (plugin.API != PLUGIN_QUERY_API_VERSION)
  729. return;
  730. PluginInfo plugincopy = plugin;
  731. switch (ptype)
  732. {
  733. case PLUGIN_INTERNAL:
  734. case PLUGIN_LV2:
  735. case PLUGIN_SF2:
  736. case PLUGIN_SFZ:
  737. case PLUGIN_JSFX:
  738. plugincopy.build = BINARY_NATIVE;
  739. break;
  740. default:
  741. break;
  742. }
  743. const int index = fLastTableIndex;
  744. #if 0
  745. const bool isFav = bool(self._createFavoritePluginDict(plugin) in self.fFavoritePlugins)
  746. #else
  747. const bool isFav = false;
  748. #endif
  749. QTableWidgetItem* const itemFav = new QTableWidgetItem;
  750. itemFav->setCheckState(isFav ? Qt::Checked : Qt::Unchecked);
  751. itemFav->setText(isFav ? " " : " ");
  752. const QString pluginText = (plugin.name + plugin.label + plugin.maker + plugin.filename).toLower();
  753. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_FAVORITE, itemFav);
  754. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_NAME, new QTableWidgetItem(plugin.name));
  755. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_LABEL, new QTableWidgetItem(plugin.label));
  756. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_MAKER, new QTableWidgetItem(plugin.maker));
  757. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_BINARY, new QTableWidgetItem(QFileInfo(plugin.filename).fileName()));
  758. QTableWidgetItem* const itemName = ui.tableWidget->item(index, TABLEWIDGET_ITEM_NAME);
  759. itemName->setData(Qt::UserRole+1, asVariant(plugincopy));
  760. itemName->setData(Qt::UserRole+2, pluginText);
  761. fLastTableIndex += 1;
  762. }
  763. uint reAddInternalHelper(QSafePluginListSettings& settingsDB, const PluginType ptype, const char* const path)
  764. {
  765. QString ptypeStr, ptypeStrTr;
  766. switch (ptype)
  767. {
  768. case PLUGIN_INTERNAL:
  769. ptypeStr = "Internal";
  770. ptypeStrTr = tr("Internal");
  771. break;
  772. case PLUGIN_LV2:
  773. ptypeStr = "LV2";
  774. ptypeStrTr = ptypeStr;
  775. break;
  776. case PLUGIN_AU:
  777. ptypeStr = "AU";
  778. ptypeStrTr = ptypeStr;
  779. break;
  780. case PLUGIN_SFZ:
  781. ptypeStr = "SFZ";
  782. ptypeStrTr = ptypeStr;
  783. break;
  784. // TODO(jsfx) what to do here?
  785. default:
  786. return 0;
  787. }
  788. QPluginInfoList plugins = settingsDB.valuePluginInfoList("Plugins/" + ptypeStr);
  789. uint pluginCount = settingsDB.valueUInt("PluginCount/" + ptypeStr, 0);
  790. if (ptype == PLUGIN_AU)
  791. carla_juce_init();
  792. const uint pluginCountNew = carla_get_cached_plugin_count(ptype, path);
  793. #if 0
  794. if (pluginCountNew != pluginCount || plugins.size() != pluginCount ||
  795. (plugins.size() > 0 && plugins[0].API != PLUGIN_QUERY_API_VERSION))
  796. #endif
  797. {
  798. plugins.clear();
  799. pluginCount = pluginCountNew;
  800. QApplication::instance()->processEvents(QEventLoop::ExcludeUserInputEvents, 50);
  801. if (ptype == PLUGIN_AU)
  802. carla_juce_idle();
  803. for (uint i=0; i<pluginCountNew; ++i)
  804. {
  805. const CarlaCachedPluginInfo* const descInfo = carla_get_cached_plugin_info(ptype, i);
  806. if (descInfo == nullptr)
  807. continue;
  808. const PluginInfo info = checkPluginCached(descInfo, ptype);
  809. plugins.append(info);
  810. if ((i % 50) == 0)
  811. {
  812. QApplication::instance()->processEvents(QEventLoop::ExcludeUserInputEvents, 50);
  813. if (ptype == PLUGIN_AU)
  814. carla_juce_idle();
  815. }
  816. }
  817. settingsDB.setValue("Plugins/" + ptypeStr, plugins);
  818. settingsDB.setValue("PluginCount/" + ptypeStr, pluginCount);
  819. }
  820. if (ptype == PLUGIN_AU)
  821. carla_juce_cleanup();
  822. // prepare rows in advance
  823. ui.tableWidget->setRowCount(fLastTableIndex + plugins.size());
  824. for (const PluginInfo& plugin : plugins)
  825. addPluginToTable(plugin, ptype);
  826. return pluginCount;
  827. }
  828. #endif
  829. void reAddPlugins()
  830. {
  831. #ifdef CARLA_FRONTEND_NO_CACHED_PLUGIN_API
  832. fLastTableIndex = 0;
  833. ui.tableWidget->setSortingEnabled(false);
  834. ui.tableWidget->clearContents();
  835. DefaultPaths paths;
  836. paths.init();
  837. paths.loadFromEnv();
  838. CarlaPluginDiscoveryHandle handle = carla_plugin_discovery_start("/usr/lib/carla/carla-discovery-native",
  839. PLUGIN_VST3,
  840. paths.vst3.toUtf8().constData(),
  841. _discoveryCallback,
  842. this);
  843. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  844. while (carla_plugin_discovery_idle(handle))
  845. QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 50);
  846. carla_plugin_discovery_stop(handle);
  847. ui.tableWidget->setRowCount(fLastTableIndex);
  848. constexpr const char* const txt = "Have %1 plugins";
  849. ui.label->setText(fRealParent->tr(txt)
  850. .arg(QString::number(fLastTableIndex))
  851. );
  852. #else
  853. QSafePluginListSettings settingsDB("falkTX", "CarlaPlugins5");
  854. fLastTableIndex = 0;
  855. ui.tableWidget->setSortingEnabled(false);
  856. ui.tableWidget->clearContents();
  857. DefaultPaths paths;
  858. paths.init();
  859. paths.loadFromEnv();
  860. QCarlaString LV2_PATH;
  861. {
  862. const QSafeSettings settings("falkTX", "Carla2");
  863. LV2_PATH = settings.valueString(CARLA_KEY_PATHS_LV2, paths.lv2);
  864. }
  865. // ------------------------------------------------------------------------------------------------------------
  866. // plugins handled through backend
  867. const uint internalCount = reAddInternalHelper(settingsDB, PLUGIN_INTERNAL, "");
  868. const uint lv2Count = reAddInternalHelper(settingsDB, PLUGIN_LV2, LV2_PATH.toUtf8());
  869. #ifdef CARLA_OS_MAC
  870. const uint auCount = reAddInternalHelper(settingsDB, PLUGIN_AU, "");
  871. #else
  872. const uint auCount = 0;
  873. #endif
  874. // ------------------------------------------------------------------------------------------------------------
  875. // LADSPA
  876. QList<QPluginInfoList> ladspaPlugins;
  877. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_native");
  878. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_posix32");
  879. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_posix64");
  880. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_win32");
  881. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_win64");
  882. // ------------------------------------------------------------------------------------------------------------
  883. // DSSI
  884. QList<QPluginInfoList> dssiPlugins;
  885. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_native");
  886. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_posix32");
  887. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_posix64");
  888. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_win32");
  889. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_win64");
  890. // ------------------------------------------------------------------------------------------------------------
  891. // VST2
  892. QList<QPluginInfoList> vst2Plugins;
  893. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_native");
  894. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_posix32");
  895. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_posix64");
  896. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_win32");
  897. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_win64");
  898. // ------------------------------------------------------------------------------------------------------------
  899. // VST3
  900. QList<QPluginInfoList> vst3Plugins;
  901. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_native");
  902. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_posix32");
  903. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_posix64");
  904. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_win32");
  905. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_win64");
  906. // ------------------------------------------------------------------------------------------------------------
  907. // CLAP
  908. QList<QPluginInfoList> clapPlugins;
  909. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_native");
  910. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_posix32");
  911. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_posix64");
  912. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_win32");
  913. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_win64");
  914. #ifdef CARLA_OS_MAC
  915. // ------------------------------------------------------------------------------------------------------------
  916. // AU (extra non-cached)
  917. QList<QPluginInfoList> auPlugins32;
  918. auPlugins32 += settingsDB.valuePluginInfoList("Plugins/AU_posix32");
  919. #endif
  920. // ------------------------------------------------------------------------------------------------------------
  921. // JSFX
  922. QPluginInfoList jsfxPlugins = settingsDB.valuePluginInfoList("Plugins/JSFX");
  923. // ------------------------------------------------------------------------------------------------------------
  924. // Kits
  925. QList<QPluginInfoList> sf2s;
  926. sf2s += settingsDB.valuePluginInfoList("Plugins/SF2");
  927. QPluginInfoList sfzs = settingsDB.valuePluginInfoList("Plugins/SFZ");
  928. // ------------------------------------------------------------------------------------------------------------
  929. // count plugins first, so we can create rows in advance
  930. int ladspaCount = 0;
  931. int dssiCount = 0;
  932. int vstCount = 0;
  933. int vst3Count = 0;
  934. int clapCount = 0;
  935. int au32Count = 0;
  936. int jsfxCount = jsfxPlugins.size();
  937. int sf2Count = 0;
  938. int sfzCount = sfzs.size();
  939. for (const QPluginInfoList& plugins : ladspaPlugins)
  940. ladspaCount += plugins.size();
  941. for (const QPluginInfoList& plugins : dssiPlugins)
  942. dssiCount += plugins.size();
  943. for (const QPluginInfoList& plugins : vst2Plugins)
  944. vstCount += plugins.size();
  945. for (const QPluginInfoList& plugins : vst3Plugins)
  946. vst3Count += plugins.size();
  947. for (const QPluginInfoList& plugins : clapPlugins)
  948. clapCount += plugins.size();
  949. #ifdef CARLA_OS_MAC
  950. for (const QPluginInfoList& plugins : auPlugins32)
  951. au32Count += plugins.size();
  952. #endif
  953. for (const QPluginInfoList& plugins : sf2s)
  954. sf2Count += plugins.size();
  955. ui.tableWidget->setRowCount(fLastTableIndex +
  956. ladspaCount + dssiCount + vstCount + vst3Count + clapCount +
  957. auCount + au32Count + jsfxCount + sf2Count + sfzCount);
  958. constexpr const char* const txt = "Have %1 Internal, %2 LADSPA, %3 DSSI, %4 LV2, %5 VST2, %6 VST3, %7 CLAP"
  959. #ifdef CARLA_OS_MAC
  960. ", %8 AudioUnit and %9 JSFX plugins, plus %10 Sound Kits"
  961. #endif
  962. " and %8 JSFX plugins, plus %9 Sound Kits";
  963. ui.label->setText(fRealParent->tr(txt)
  964. .arg(QString::number(internalCount))
  965. .arg(QString::number(ladspaCount))
  966. .arg(QString::number(dssiCount))
  967. .arg(QString::number(lv2Count))
  968. .arg(QString::number(vstCount))
  969. .arg(QString::number(vst3Count))
  970. .arg(QString::number(clapCount))
  971. #ifdef CARLA_OS_MAC
  972. .arg(QString::number(auCount+au32Count))
  973. #endif
  974. .arg(QString::number(jsfxCount))
  975. .arg(QString::number(sf2Count+sfzCount))
  976. );
  977. // ------------------------------------------------------------------------------------------------------------
  978. // now add all plugins to the table
  979. for (const QPluginInfoList& plugins : ladspaPlugins)
  980. for (const PluginInfo& plugin : plugins)
  981. addPluginToTable(plugin, PLUGIN_LADSPA);
  982. for (const QPluginInfoList& plugins : dssiPlugins)
  983. for (const PluginInfo& plugin : plugins)
  984. addPluginToTable(plugin, PLUGIN_DSSI);
  985. for (const QPluginInfoList& plugins : vst2Plugins)
  986. for (const PluginInfo& plugin : plugins)
  987. addPluginToTable(plugin, PLUGIN_VST2);
  988. for (const QPluginInfoList& plugins : vst3Plugins)
  989. for (const PluginInfo& plugin : plugins)
  990. addPluginToTable(plugin, PLUGIN_VST3);
  991. for (const QPluginInfoList& plugins : clapPlugins)
  992. for (const PluginInfo& plugin : plugins)
  993. addPluginToTable(plugin, PLUGIN_CLAP);
  994. #ifdef CARLA_OS_MAC
  995. for (const QPluginInfoList& plugins : auPlugins32)
  996. for (const PluginInfo& plugin : plugins)
  997. addPluginToTable(plugin, PLUGIN_AU);
  998. #endif
  999. for (const PluginInfo& plugin : jsfxPlugins)
  1000. addPluginToTable(plugin, PLUGIN_JSFX);
  1001. for (const QPluginInfoList& sf2 : sf2s)
  1002. for (const PluginInfo& sf2_i : sf2)
  1003. addPluginToTable(sf2_i, PLUGIN_SF2);
  1004. for (const PluginInfo& sfz : sfzs)
  1005. addPluginToTable(sfz, PLUGIN_SFZ);
  1006. #endif
  1007. // ------------------------------------------------------------------------------------------------------------
  1008. ui.tableWidget->setSortingEnabled(true);
  1009. checkFilters();
  1010. checkPlugin(ui.tableWidget->currentRow());
  1011. }
  1012. void checkPlugin(const int row)
  1013. {
  1014. if (row >= 0)
  1015. {
  1016. ui.b_add->setEnabled(true);
  1017. PluginInfo plugin = asPluginInfo(ui.tableWidget->item(row, TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+1));
  1018. const bool isSynth = plugin.hints & PLUGIN_IS_SYNTH;
  1019. const bool isEffect = plugin.audioIns > 0 && plugin.audioOuts > 0 && !isSynth;
  1020. const bool isMidi = plugin.audioIns == 0 &&
  1021. plugin.audioOuts == 0 &&
  1022. plugin.midiIns > 0 && plugin.midiOuts > 0;
  1023. // const bool isKit = plugin['type'] in (PLUGIN_SF2, PLUGIN_SFZ);
  1024. // const bool isOther = ! (isEffect || isSynth || isMidi || isKit);
  1025. QString ptype;
  1026. /**/ if (isSynth)
  1027. ptype = "Instrument";
  1028. else if (isEffect)
  1029. ptype = "Effect";
  1030. else if (isMidi)
  1031. ptype = "MIDI Plugin";
  1032. else
  1033. ptype = "Other";
  1034. QString parch;
  1035. /**/ if (plugin.build == BINARY_NATIVE)
  1036. parch = fTrNative;
  1037. else if (plugin.build == BINARY_POSIX32)
  1038. parch = "posix32";
  1039. else if (plugin.build == BINARY_POSIX64)
  1040. parch = "posix64";
  1041. else if (plugin.build == BINARY_WIN32)
  1042. parch = "win32";
  1043. else if (plugin.build == BINARY_WIN64)
  1044. parch = "win64";
  1045. else if (plugin.build == BINARY_OTHER)
  1046. parch = tr("Other");
  1047. else if (plugin.build == BINARY_WIN32)
  1048. parch = tr("Unknown");
  1049. ui.l_format->setText(getPluginTypeAsString(plugin.type));
  1050. ui.l_type->setText(ptype);
  1051. ui.l_arch->setText(parch);
  1052. ui.l_id->setText(QString::number(plugin.uniqueId));
  1053. ui.l_ains->setText(QString::number(plugin.audioIns));
  1054. ui.l_aouts->setText(QString::number(plugin.audioOuts));
  1055. ui.l_cvins->setText(QString::number(plugin.cvIns));
  1056. ui.l_cvouts->setText(QString::number(plugin.cvOuts));
  1057. ui.l_mins->setText(QString::number(plugin.midiIns));
  1058. ui.l_mouts->setText(QString::number(plugin.midiOuts));
  1059. ui.l_pins->setText(QString::number(plugin.parametersIns));
  1060. ui.l_pouts->setText(QString::number(plugin.parametersOuts));
  1061. ui.l_gui->setText(plugin.hints & PLUGIN_HAS_CUSTOM_UI ? fTrYes : fTrNo);
  1062. ui.l_idisp->setText(plugin.hints & PLUGIN_HAS_INLINE_DISPLAY ? fTrYes : fTrNo);
  1063. ui.l_bridged->setText(plugin.hints & PLUGIN_IS_BRIDGE ? fTrYes : fTrNo);
  1064. ui.l_synth->setText(isSynth ? fTrYes : fTrNo);
  1065. }
  1066. else
  1067. {
  1068. ui.b_add->setEnabled(false);
  1069. ui.l_format->setText("---");
  1070. ui.l_type->setText("---");
  1071. ui.l_arch->setText("---");
  1072. ui.l_id->setText("---");
  1073. ui.l_ains->setText("---");
  1074. ui.l_aouts->setText("---");
  1075. ui.l_cvins->setText("---");
  1076. ui.l_cvouts->setText("---");
  1077. ui.l_mins->setText("---");
  1078. ui.l_mouts->setText("---");
  1079. ui.l_pins->setText("---");
  1080. ui.l_pouts->setText("---");
  1081. ui.l_gui->setText("---");
  1082. ui.l_idisp->setText("---");
  1083. ui.l_bridged->setText("---");
  1084. ui.l_synth->setText("---");
  1085. }
  1086. }
  1087. };
  1088. PluginListDialog::PluginListDialog(QWidget* const parent, const HostSettings& hostSettings)
  1089. : QDialog(parent),
  1090. self(Self::create(parent))
  1091. {
  1092. self.ui.setupUi(this);
  1093. self.hostSettings = hostSettings;
  1094. // ----------------------------------------------------------------------------------------------------------------
  1095. // Set-up GUI
  1096. self.ui.b_add->setEnabled(false);
  1097. addAction(self.ui.act_focus_search);
  1098. QObject::connect(self.ui.act_focus_search, &QAction::triggered,
  1099. this, &PluginListDialog::slot_focusSearchFieldAndSelectAll);
  1100. #if BINARY_NATIVE == BINARY_POSIX32 || BINARY_NATIVE == BINARY_WIN32
  1101. self.ui.ch_bridged->setText(tr("Bridged (64bit)"));
  1102. #else
  1103. self.ui.ch_bridged->setText(tr("Bridged (32bit)"));
  1104. #endif
  1105. #if !(defined(CARLA_OS_LINUX) || defined(CARLA_OS_MAC))
  1106. self.ui.ch_bridged_wine->setChecked(false);
  1107. self.ui.ch_bridged_wine->setEnabled(false);
  1108. #endif
  1109. #ifdef CARLA_OS_MAC
  1110. setWindowModality(Qt::WindowModal);
  1111. #else
  1112. self.ui.ch_au->setChecked(false);
  1113. self.ui.ch_au->setEnabled(false);
  1114. self.ui.ch_au->setVisible(false);
  1115. #endif
  1116. self.ui.tab_info->tabBar()->hide();
  1117. self.ui.tab_reqs->tabBar()->hide();
  1118. // FIXME, why /2 needed?
  1119. self.ui.tab_info->setMinimumWidth(self.ui.la_id->width()/2 +
  1120. fontMetricsHorizontalAdvance(self.ui.l_id->fontMetrics(), "9999999999") + 6*3);
  1121. setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
  1122. // ----------------------------------------------------------------------------------------------------------------
  1123. // Load settings
  1124. loadSettings();
  1125. // ----------------------------------------------------------------------------------------------------------------
  1126. // Disable bridges if not enabled in settings
  1127. #if 0
  1128. // NOTE: We Assume win32 carla build will not run win64 plugins
  1129. if (WINDOWS and not kIs64bit) or not host.showPluginBridges:
  1130. self.ui.ch_native.setChecked(True)
  1131. self.ui.ch_native.setEnabled(False)
  1132. self.ui.ch_native.setVisible(True)
  1133. self.ui.ch_bridged.setChecked(False)
  1134. self.ui.ch_bridged.setEnabled(False)
  1135. self.ui.ch_bridged.setVisible(False)
  1136. self.ui.ch_bridged_wine.setChecked(False)
  1137. self.ui.ch_bridged_wine.setEnabled(False)
  1138. self.ui.ch_bridged_wine.setVisible(False)
  1139. elif not host.showWineBridges:
  1140. self.ui.ch_bridged_wine.setChecked(False)
  1141. self.ui.ch_bridged_wine.setEnabled(False)
  1142. self.ui.ch_bridged_wine.setVisible(False)
  1143. #endif
  1144. // ----------------------------------------------------------------------------------------------------------------
  1145. // Set-up Icons
  1146. if (hostSettings.useSystemIcons)
  1147. {
  1148. #if 0
  1149. self.ui.b_add.setIcon(getIcon('list-add', 16, 'svgz'))
  1150. self.ui.b_cancel.setIcon(getIcon('dialog-cancel', 16, 'svgz'))
  1151. self.ui.b_clear_filters.setIcon(getIcon('edit-clear', 16, 'svgz'))
  1152. self.ui.b_refresh.setIcon(getIcon('view-refresh', 16, 'svgz'))
  1153. QTableWidgetItem* const hhi = self.ui.tableWidget->horizontalHeaderItem(self.TABLEWIDGET_ITEM_FAVORITE);
  1154. hhi.setIcon(getIcon('bookmarks', 16, 'svgz'))
  1155. #endif
  1156. }
  1157. // ----------------------------------------------------------------------------------------------------------------
  1158. // Set-up connections
  1159. QObject::connect(this, &QDialog::finished, this, &PluginListDialog::slot_saveSettings);
  1160. QObject::connect(self.ui.b_add, &QPushButton::clicked, this, &PluginListDialog::slot_addPlugin);
  1161. QObject::connect(self.ui.b_cancel, &QPushButton::clicked, this, &QDialog::reject);
  1162. QObject::connect(self.ui.b_refresh, &QPushButton::clicked, this, &PluginListDialog::slot_refreshPlugins);
  1163. QObject::connect(self.ui.b_clear_filters, &QPushButton::clicked, this, &PluginListDialog::slot_clearFilters);
  1164. QObject::connect(self.ui.lineEdit, &QLineEdit::textChanged, this, &PluginListDialog::slot_checkFilters);
  1165. QObject::connect(self.ui.tableWidget, &QTableWidget::currentCellChanged,
  1166. this, &PluginListDialog::slot_checkPlugin);
  1167. QObject::connect(self.ui.tableWidget, &QTableWidget::cellClicked,
  1168. this, &PluginListDialog::slot_cellClicked);
  1169. QObject::connect(self.ui.tableWidget, &QTableWidget::cellDoubleClicked,
  1170. this, &PluginListDialog::slot_cellDoubleClicked);
  1171. QObject::connect(self.ui.ch_internal, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1172. QObject::connect(self.ui.ch_ladspa, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1173. QObject::connect(self.ui.ch_dssi, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1174. QObject::connect(self.ui.ch_lv2, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1175. QObject::connect(self.ui.ch_vst, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1176. QObject::connect(self.ui.ch_vst3, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1177. QObject::connect(self.ui.ch_clap, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1178. QObject::connect(self.ui.ch_au, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1179. QObject::connect(self.ui.ch_jsfx, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1180. QObject::connect(self.ui.ch_kits, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1181. QObject::connect(self.ui.ch_effects, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1182. QObject::connect(self.ui.ch_instruments, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1183. QObject::connect(self.ui.ch_midi, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1184. QObject::connect(self.ui.ch_other, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1185. QObject::connect(self.ui.ch_native, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1186. QObject::connect(self.ui.ch_bridged, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1187. QObject::connect(self.ui.ch_bridged_wine, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1188. QObject::connect(self.ui.ch_favorites, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1189. QObject::connect(self.ui.ch_rtsafe, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1190. QObject::connect(self.ui.ch_cv, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1191. QObject::connect(self.ui.ch_gui, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1192. QObject::connect(self.ui.ch_inline_display, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1193. QObject::connect(self.ui.ch_stereo, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1194. QObject::connect(self.ui.ch_cat_all, &QCheckBox::clicked,
  1195. this, &PluginListDialog::slot_checkFiltersCategoryAll);
  1196. QObject::connect(self.ui.ch_cat_delay, &QCheckBox::clicked,
  1197. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1198. QObject::connect(self.ui.ch_cat_distortion, &QCheckBox::clicked,
  1199. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1200. QObject::connect(self.ui.ch_cat_dynamics, &QCheckBox::clicked,
  1201. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1202. QObject::connect(self.ui.ch_cat_eq, &QCheckBox::clicked,
  1203. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1204. QObject::connect(self.ui.ch_cat_filter, &QCheckBox::clicked,
  1205. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1206. QObject::connect(self.ui.ch_cat_modulator, &QCheckBox::clicked,
  1207. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1208. QObject::connect(self.ui.ch_cat_synth, &QCheckBox::clicked,
  1209. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1210. QObject::connect(self.ui.ch_cat_utility, &QCheckBox::clicked,
  1211. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1212. QObject::connect(self.ui.ch_cat_other, &QCheckBox::clicked, this,
  1213. &PluginListDialog::slot_checkFiltersCategorySpecific);
  1214. // ----------------------------------------------------------------------------------------------------------------
  1215. // Post-connect setup
  1216. self.reAddPlugins();
  1217. slot_focusSearchFieldAndSelectAll();
  1218. }
  1219. PluginListDialog::~PluginListDialog()
  1220. {
  1221. delete &self;
  1222. }
  1223. // --------------------------------------------------------------------------------------------------------------------
  1224. // public methods
  1225. const PluginInfo& PluginListDialog::getSelectedPluginInfo() const
  1226. {
  1227. return self.fRetPlugin;
  1228. }
  1229. // --------------------------------------------------------------------------------------------------------------------
  1230. // protected methods
  1231. void PluginListDialog::showEvent(QShowEvent* const event)
  1232. {
  1233. slot_focusSearchFieldAndSelectAll();
  1234. QDialog::showEvent(event);
  1235. }
  1236. // --------------------------------------------------------------------------------------------------------------------
  1237. // private methods
  1238. void PluginListDialog::loadSettings()
  1239. {
  1240. const QSafeSettings settings("falkTX", "CarlaDatabase2");
  1241. self.fFavoritePlugins = settings.valueStringList("PluginDatabase/Favorites");
  1242. self.fFavoritePluginsChanged = false;
  1243. restoreGeometry(settings.valueByteArray("PluginDatabase/Geometry"));
  1244. self.ui.ch_effects->setChecked(settings.valueBool("PluginDatabase/ShowEffects", true));
  1245. self.ui.ch_instruments->setChecked(settings.valueBool("PluginDatabase/ShowInstruments", true));
  1246. self.ui.ch_midi->setChecked(settings.valueBool("PluginDatabase/ShowMIDI", true));
  1247. self.ui.ch_other->setChecked(settings.valueBool("PluginDatabase/ShowOther", true));
  1248. self.ui.ch_internal->setChecked(settings.valueBool("PluginDatabase/ShowInternal", true));
  1249. self.ui.ch_ladspa->setChecked(settings.valueBool("PluginDatabase/ShowLADSPA", true));
  1250. self.ui.ch_dssi->setChecked(settings.valueBool("PluginDatabase/ShowDSSI", true));
  1251. self.ui.ch_lv2->setChecked(settings.valueBool("PluginDatabase/ShowLV2", true));
  1252. self.ui.ch_vst->setChecked(settings.valueBool("PluginDatabase/ShowVST2", true));
  1253. self.ui.ch_vst3->setChecked(settings.valueBool("PluginDatabase/ShowVST3", true));
  1254. self.ui.ch_clap->setChecked(settings.valueBool("PluginDatabase/ShowCLAP", true));
  1255. #ifdef CARLA_OS_MAC
  1256. self.ui.ch_au->setChecked(settings.valueBool("PluginDatabase/ShowAU", true));
  1257. #endif
  1258. self.ui.ch_jsfx->setChecked(settings.valueBool("PluginDatabase/ShowJSFX", true));
  1259. self.ui.ch_kits->setChecked(settings.valueBool("PluginDatabase/ShowKits", true));
  1260. self.ui.ch_native->setChecked(settings.valueBool("PluginDatabase/ShowNative", true));
  1261. self.ui.ch_bridged->setChecked(settings.valueBool("PluginDatabase/ShowBridged", true));
  1262. self.ui.ch_bridged_wine->setChecked(settings.valueBool("PluginDatabase/ShowBridgedWine", true));
  1263. self.ui.ch_favorites->setChecked(settings.valueBool("PluginDatabase/ShowFavorites", false));
  1264. self.ui.ch_rtsafe->setChecked(settings.valueBool("PluginDatabase/ShowRtSafe", false));
  1265. self.ui.ch_cv->setChecked(settings.valueBool("PluginDatabase/ShowHasCV", false));
  1266. self.ui.ch_gui->setChecked(settings.valueBool("PluginDatabase/ShowHasGUI", false));
  1267. self.ui.ch_inline_display->setChecked(settings.valueBool("PluginDatabase/ShowHasInlineDisplay", false));
  1268. self.ui.ch_stereo->setChecked(settings.valueBool("PluginDatabase/ShowStereoOnly", false));
  1269. self.ui.lineEdit->setText(settings.valueString("PluginDatabase/SearchText", ""));
  1270. const QString categories = settings.valueString("PluginDatabase/ShowCategory", "all");
  1271. if (categories == "all" or categories.length() < 2)
  1272. {
  1273. self.ui.ch_cat_all->setChecked(true);
  1274. self.ui.ch_cat_delay->setChecked(false);
  1275. self.ui.ch_cat_distortion->setChecked(false);
  1276. self.ui.ch_cat_dynamics->setChecked(false);
  1277. self.ui.ch_cat_eq->setChecked(false);
  1278. self.ui.ch_cat_filter->setChecked(false);
  1279. self.ui.ch_cat_modulator->setChecked(false);
  1280. self.ui.ch_cat_synth->setChecked(false);
  1281. self.ui.ch_cat_utility->setChecked(false);
  1282. self.ui.ch_cat_other->setChecked(false);
  1283. }
  1284. else
  1285. {
  1286. self.ui.ch_cat_all->setChecked(false);
  1287. self.ui.ch_cat_delay->setChecked(categories.contains(":delay:"));
  1288. self.ui.ch_cat_distortion->setChecked(categories.contains(":distortion:"));
  1289. self.ui.ch_cat_dynamics->setChecked(categories.contains(":dynamics:"));
  1290. self.ui.ch_cat_eq->setChecked(categories.contains(":eq:"));
  1291. self.ui.ch_cat_filter->setChecked(categories.contains(":filter:"));
  1292. self.ui.ch_cat_modulator->setChecked(categories.contains(":modulator:"));
  1293. self.ui.ch_cat_synth->setChecked(categories.contains(":synth:"));
  1294. self.ui.ch_cat_utility->setChecked(categories.contains(":utility:"));
  1295. self.ui.ch_cat_other->setChecked(categories.contains(":other:"));
  1296. }
  1297. const QByteArray tableGeometry = settings.valueByteArray("PluginDatabase/TableGeometry_6");
  1298. QHeaderView* const horizontalHeader = self.ui.tableWidget->horizontalHeader();
  1299. if (! tableGeometry.isNull())
  1300. {
  1301. horizontalHeader->restoreState(tableGeometry);
  1302. }
  1303. else
  1304. {
  1305. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_NAME, 250);
  1306. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_LABEL, 200);
  1307. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_MAKER, 150);
  1308. self.ui.tableWidget->sortByColumn(self.TABLEWIDGET_ITEM_NAME, Qt::AscendingOrder);
  1309. }
  1310. horizontalHeader->setSectionResizeMode(self.TABLEWIDGET_ITEM_FAVORITE, QHeaderView::Fixed);
  1311. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_FAVORITE, 24);
  1312. self.ui.tableWidget->setSortingEnabled(true);
  1313. }
  1314. // -----------------------------------------------------------------------------------------------------------------
  1315. // private slots
  1316. void PluginListDialog::slot_cellClicked(int row, int column)
  1317. {
  1318. if (column != self.TABLEWIDGET_ITEM_FAVORITE)
  1319. return;
  1320. const QTableWidgetItem* const widget = self.ui.tableWidget->item(row, self.TABLEWIDGET_ITEM_FAVORITE);
  1321. const PluginInfo plugin = asPluginInfo(self.ui.tableWidget->item(row, self.TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+1));
  1322. #if 0
  1323. plugin = self._createFavoritePluginDict(plugin);
  1324. #endif
  1325. if (widget->checkState() == Qt::Checked)
  1326. {
  1327. #if 0
  1328. if (not plugin in self.fFavoritePlugins)
  1329. {
  1330. self.fFavoritePlugins.append(plugin);
  1331. self.fFavoritePluginsChanged = true;
  1332. }
  1333. #endif
  1334. }
  1335. else
  1336. {
  1337. #if 0
  1338. try:
  1339. self.fFavoritePlugins.remove(plugin);
  1340. self.fFavoritePluginsChanged = True;
  1341. except ValueError:
  1342. pass
  1343. #endif
  1344. }
  1345. }
  1346. void PluginListDialog::slot_cellDoubleClicked(int, int column)
  1347. {
  1348. if (column != self.TABLEWIDGET_ITEM_FAVORITE)
  1349. slot_addPlugin();
  1350. }
  1351. void PluginListDialog::slot_focusSearchFieldAndSelectAll()
  1352. {
  1353. self.ui.lineEdit->setFocus();
  1354. self.ui.lineEdit->selectAll();
  1355. }
  1356. void PluginListDialog::slot_addPlugin()
  1357. {
  1358. if (self.ui.tableWidget->currentRow() >= 0)
  1359. {
  1360. self.fRetPlugin = asPluginInfo(self.ui.tableWidget->item(self.ui.tableWidget->currentRow(),
  1361. self.TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+1));
  1362. accept();
  1363. }
  1364. else
  1365. {
  1366. reject();
  1367. }
  1368. }
  1369. void PluginListDialog::slot_checkPlugin(const int row)
  1370. {
  1371. self.checkPlugin(row);
  1372. }
  1373. void PluginListDialog::slot_checkFilters()
  1374. {
  1375. self.checkFilters();
  1376. }
  1377. void PluginListDialog::slot_checkFiltersCategoryAll(const bool clicked)
  1378. {
  1379. const bool notClicked = !clicked;
  1380. self.ui.ch_cat_delay->setChecked(notClicked);
  1381. self.ui.ch_cat_distortion->setChecked(notClicked);
  1382. self.ui.ch_cat_dynamics->setChecked(notClicked);
  1383. self.ui.ch_cat_eq->setChecked(notClicked);
  1384. self.ui.ch_cat_filter->setChecked(notClicked);
  1385. self.ui.ch_cat_modulator->setChecked(notClicked);
  1386. self.ui.ch_cat_synth->setChecked(notClicked);
  1387. self.ui.ch_cat_utility->setChecked(notClicked);
  1388. self.ui.ch_cat_other->setChecked(notClicked);
  1389. self.checkFilters();
  1390. }
  1391. void PluginListDialog::slot_checkFiltersCategorySpecific(bool clicked)
  1392. {
  1393. if (clicked)
  1394. {
  1395. self.ui.ch_cat_all->setChecked(false);
  1396. }
  1397. else if (! (self.ui.ch_cat_delay->isChecked() ||
  1398. self.ui.ch_cat_distortion->isChecked() ||
  1399. self.ui.ch_cat_dynamics->isChecked() ||
  1400. self.ui.ch_cat_eq->isChecked() ||
  1401. self.ui.ch_cat_filter->isChecked() ||
  1402. self.ui.ch_cat_modulator->isChecked() ||
  1403. self.ui.ch_cat_synth->isChecked() ||
  1404. self.ui.ch_cat_utility->isChecked() ||
  1405. self.ui.ch_cat_other->isChecked()))
  1406. {
  1407. self.ui.ch_cat_all->setChecked(true);
  1408. }
  1409. self.checkFilters();
  1410. }
  1411. void PluginListDialog::slot_refreshPlugins()
  1412. {
  1413. #if 0
  1414. if (PluginRefreshW(this, self.hostSettings, self.hasLoadedLv2Plugins).exec())
  1415. reAddPlugins();
  1416. #endif
  1417. }
  1418. void PluginListDialog::slot_clearFilters()
  1419. {
  1420. blockSignals(true);
  1421. self.ui.ch_internal->setChecked(true);
  1422. self.ui.ch_ladspa->setChecked(true);
  1423. self.ui.ch_dssi->setChecked(true);
  1424. self.ui.ch_lv2->setChecked(true);
  1425. self.ui.ch_vst->setChecked(true);
  1426. self.ui.ch_vst3->setChecked(true);
  1427. self.ui.ch_clap->setChecked(true);
  1428. self.ui.ch_jsfx->setChecked(true);
  1429. self.ui.ch_kits->setChecked(true);
  1430. self.ui.ch_instruments->setChecked(true);
  1431. self.ui.ch_effects->setChecked(true);
  1432. self.ui.ch_midi->setChecked(true);
  1433. self.ui.ch_other->setChecked(true);
  1434. self.ui.ch_native->setChecked(true);
  1435. self.ui.ch_bridged->setChecked(false);
  1436. self.ui.ch_bridged_wine->setChecked(false);
  1437. self.ui.ch_favorites->setChecked(false);
  1438. self.ui.ch_rtsafe->setChecked(false);
  1439. self.ui.ch_stereo->setChecked(false);
  1440. self.ui.ch_cv->setChecked(false);
  1441. self.ui.ch_gui->setChecked(false);
  1442. self.ui.ch_inline_display->setChecked(false);
  1443. if (self.ui.ch_au->isEnabled())
  1444. self.ui.ch_au->setChecked(true);
  1445. self.ui.ch_cat_all->setChecked(true);
  1446. self.ui.ch_cat_delay->setChecked(false);
  1447. self.ui.ch_cat_distortion->setChecked(false);
  1448. self.ui.ch_cat_dynamics->setChecked(false);
  1449. self.ui.ch_cat_eq->setChecked(false);
  1450. self.ui.ch_cat_filter->setChecked(false);
  1451. self.ui.ch_cat_modulator->setChecked(false);
  1452. self.ui.ch_cat_synth->setChecked(false);
  1453. self.ui.ch_cat_utility->setChecked(false);
  1454. self.ui.ch_cat_other->setChecked(false);
  1455. self.ui.lineEdit->clear();
  1456. blockSignals(false);
  1457. self.checkFilters();
  1458. }
  1459. // --------------------------------------------------------------------------------------------------------------------
  1460. void PluginListDialog::slot_saveSettings()
  1461. {
  1462. QSafeSettings settings("falkTX", "CarlaDatabase2");
  1463. settings.setValue("PluginDatabase/Geometry", saveGeometry());
  1464. settings.setValue("PluginDatabase/TableGeometry_6", self.ui.tableWidget->horizontalHeader()->saveState());
  1465. settings.setValue("PluginDatabase/ShowEffects", self.ui.ch_effects->isChecked());
  1466. settings.setValue("PluginDatabase/ShowInstruments", self.ui.ch_instruments->isChecked());
  1467. settings.setValue("PluginDatabase/ShowMIDI", self.ui.ch_midi->isChecked());
  1468. settings.setValue("PluginDatabase/ShowOther", self.ui.ch_other->isChecked());
  1469. settings.setValue("PluginDatabase/ShowInternal", self.ui.ch_internal->isChecked());
  1470. settings.setValue("PluginDatabase/ShowLADSPA", self.ui.ch_ladspa->isChecked());
  1471. settings.setValue("PluginDatabase/ShowDSSI", self.ui.ch_dssi->isChecked());
  1472. settings.setValue("PluginDatabase/ShowLV2", self.ui.ch_lv2->isChecked());
  1473. settings.setValue("PluginDatabase/ShowVST2", self.ui.ch_vst->isChecked());
  1474. settings.setValue("PluginDatabase/ShowVST3", self.ui.ch_vst3->isChecked());
  1475. settings.setValue("PluginDatabase/ShowCLAP", self.ui.ch_clap->isChecked());
  1476. settings.setValue("PluginDatabase/ShowAU", self.ui.ch_au->isChecked());
  1477. settings.setValue("PluginDatabase/ShowJSFX", self.ui.ch_jsfx->isChecked());
  1478. settings.setValue("PluginDatabase/ShowKits", self.ui.ch_kits->isChecked());
  1479. settings.setValue("PluginDatabase/ShowNative", self.ui.ch_native->isChecked());
  1480. settings.setValue("PluginDatabase/ShowBridged", self.ui.ch_bridged->isChecked());
  1481. settings.setValue("PluginDatabase/ShowBridgedWine", self.ui.ch_bridged_wine->isChecked());
  1482. settings.setValue("PluginDatabase/ShowFavorites", self.ui.ch_favorites->isChecked());
  1483. settings.setValue("PluginDatabase/ShowRtSafe", self.ui.ch_rtsafe->isChecked());
  1484. settings.setValue("PluginDatabase/ShowHasCV", self.ui.ch_cv->isChecked());
  1485. settings.setValue("PluginDatabase/ShowHasGUI", self.ui.ch_gui->isChecked());
  1486. settings.setValue("PluginDatabase/ShowHasInlineDisplay", self.ui.ch_inline_display->isChecked());
  1487. settings.setValue("PluginDatabase/ShowStereoOnly", self.ui.ch_stereo->isChecked());
  1488. settings.setValue("PluginDatabase/SearchText", self.ui.lineEdit->text());
  1489. if (self.ui.ch_cat_all->isChecked())
  1490. {
  1491. settings.setValue("PluginDatabase/ShowCategory", "all");
  1492. }
  1493. else
  1494. {
  1495. QCarlaString categories;
  1496. if (self.ui.ch_cat_delay->isChecked())
  1497. categories += ":delay";
  1498. if (self.ui.ch_cat_distortion->isChecked())
  1499. categories += ":distortion";
  1500. if (self.ui.ch_cat_dynamics->isChecked())
  1501. categories += ":dynamics";
  1502. if (self.ui.ch_cat_eq->isChecked())
  1503. categories += ":eq";
  1504. if (self.ui.ch_cat_filter->isChecked())
  1505. categories += ":filter";
  1506. if (self.ui.ch_cat_modulator->isChecked())
  1507. categories += ":modulator";
  1508. if (self.ui.ch_cat_synth->isChecked())
  1509. categories += ":synth";
  1510. if (self.ui.ch_cat_utility->isChecked())
  1511. categories += ":utility";
  1512. if (self.ui.ch_cat_other->isChecked())
  1513. categories += ":other";
  1514. if (categories.isNotEmpty())
  1515. categories += ":";
  1516. settings.setValue("PluginDatabase/ShowCategory", categories);
  1517. }
  1518. if (self.fFavoritePluginsChanged)
  1519. settings.setValue("PluginDatabase/Favorites", self.fFavoritePlugins);
  1520. }
  1521. // --------------------------------------------------------------------------------------------------------------------
  1522. const PluginListDialogResults*
  1523. carla_frontend_createAndExecPluginListDialog(void* const parent/*, const HostSettings& hostSettings*/)
  1524. {
  1525. const HostSettings hostSettings = {};
  1526. PluginListDialog gui(reinterpret_cast<QWidget*>(parent), hostSettings);
  1527. if (gui.exec())
  1528. {
  1529. static PluginListDialogResults ret;
  1530. static CarlaString category;
  1531. static CarlaString filename;
  1532. static CarlaString name;
  1533. static CarlaString label;
  1534. static CarlaString maker;
  1535. const PluginInfo& plugin(gui.getSelectedPluginInfo());
  1536. category = plugin.category.toUtf8();
  1537. filename = plugin.filename.toUtf8();
  1538. name = plugin.name.toUtf8();
  1539. label = plugin.label.toUtf8();
  1540. maker = plugin.maker.toUtf8();
  1541. ret.API = plugin.API;
  1542. ret.build = plugin.build;
  1543. ret.type = plugin.type;
  1544. ret.hints = plugin.hints;
  1545. ret.category = category;
  1546. ret.filename = filename;
  1547. ret.name = name;
  1548. ret.label = label;
  1549. ret.maker = maker;
  1550. ret.audioIns = plugin.audioIns;
  1551. ret.audioOuts = plugin.audioOuts;
  1552. ret.cvIns = plugin.cvIns;
  1553. ret.cvOuts = plugin.cvOuts;
  1554. ret.midiIns = plugin.midiIns;
  1555. ret.midiOuts = plugin.midiOuts;
  1556. ret.parametersIns = plugin.parametersIns;
  1557. ret.parametersOuts = plugin.parametersOuts;
  1558. return &ret;
  1559. }
  1560. return nullptr;
  1561. }
  1562. // --------------------------------------------------------------------------------------------------------------------