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.

1888 lines
70KB

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