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.

897 lines
34KB

  1. /*
  2. * Carla plugin host
  3. * Copyright (C) 2011-2022 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 "pluginlistdialog_ui.hpp"
  28. #include <QtCore/QList>
  29. #ifdef __clang__
  30. # pragma clang diagnostic pop
  31. #elif defined(__GNUC__) && __GNUC__ >= 8
  32. # pragma GCC diagnostic pop
  33. #endif
  34. #include "qcarlastring.hpp"
  35. #include "qsafesettings.hpp"
  36. #include "CarlaBackendUtils.hpp"
  37. #include "CarlaUtils.h"
  38. #include "CarlaString.hpp"
  39. CARLA_BACKEND_USE_NAMESPACE
  40. // --------------------------------------------------------------------------------------------------------------------
  41. // Backwards-compatible horizontalAdvance/width call, depending on Qt version
  42. static inline
  43. int fontMetricsHorizontalAdvance(const QFontMetrics& fontMetrics, const QString& string)
  44. {
  45. #if QT_VERSION >= 0x50b00
  46. return fontMetrics.horizontalAdvance(string);
  47. #else
  48. return fontMetrics.width(string);
  49. #endif
  50. }
  51. // --------------------------------------------------------------------------------------------------------------------
  52. typedef QList<PluginInfo> QPluginInfoList;
  53. class QSafePluginListSettings : public QSafeSettings
  54. {
  55. public:
  56. inline QSafePluginListSettings()
  57. : QSafeSettings() {}
  58. inline QSafePluginListSettings(const QString& organization, const QString& application)
  59. : QSafeSettings(organization, application) {}
  60. QPluginInfoList valuePluginInfoList(const QString& key, QPluginInfoList defaultValue = {}) const
  61. {
  62. /*
  63. QVariant var(value(key, defaultValue));
  64. if (!var.isNull() && var.convert(QVariant::List) && var.isValid())
  65. {
  66. QList<QVariant> varVariant(var.toList());
  67. QPluginInfoList varReal;
  68. varReal.reserve(varVariant.size());
  69. for (QVariant v : varVariant)
  70. {
  71. CARLA_SAFE_ASSERT_BREAK(!v.isNull());
  72. CARLA_SAFE_ASSERT_BREAK(v.convert(QVariant::UserType));
  73. CARLA_SAFE_ASSERT_BREAK(v.isValid());
  74. // varReal.append(v.toU);
  75. }
  76. }
  77. */
  78. return defaultValue;
  79. }
  80. void setValue(const QString& key, const uint value)
  81. {
  82. QSafeSettings::setValue(key, value);
  83. }
  84. void setValue(const QString& key, const QPluginInfoList& value)
  85. {
  86. }
  87. };
  88. // --------------------------------------------------------------------------------------------------------------------
  89. // Jack Application Dialog
  90. struct PluginListDialog::Self {
  91. enum TableIndex {
  92. TABLEWIDGET_ITEM_FAVORITE,
  93. TABLEWIDGET_ITEM_NAME,
  94. TABLEWIDGET_ITEM_LABEL,
  95. TABLEWIDGET_ITEM_MAKER,
  96. TABLEWIDGET_ITEM_BINARY,
  97. };
  98. // To be changed by parent
  99. bool hasLoadedLv2Plugins = false;
  100. Ui_PluginListDialog ui;
  101. HostSettings hostSettings;
  102. int fLastTableIndex;
  103. PluginListDialogResults fRetPlugin;
  104. QWidget* fRealParent;
  105. QStringList fFavoritePlugins;
  106. bool fFavoritePluginsChanged;
  107. QString fTrYes;
  108. QString fTrNo;
  109. QString fTrNative;
  110. Self() {}
  111. static Self& create()
  112. {
  113. Self* const self = new Self();
  114. return *self;
  115. }
  116. void createFavoritePluginDict()
  117. {
  118. // return {
  119. // 'name' : plugin['name'],
  120. // 'build' : plugin['build'],
  121. // 'type' : plugin['type'],
  122. // 'filename': plugin['filename'],
  123. // 'label' : plugin['label'],
  124. // 'uniqueId': plugin['uniqueId'],
  125. // }
  126. }
  127. void checkFilters()
  128. {
  129. }
  130. void addPluginToTable(uint plugin, const PluginType ptype)
  131. {
  132. }
  133. PluginInfo checkPluginCached(const CarlaCachedPluginInfo* const desc, const PluginType ptype)
  134. {
  135. PluginInfo pinfo = {};
  136. pinfo.build = BINARY_NATIVE;
  137. pinfo.type = ptype;
  138. pinfo.hints = desc->hints;
  139. pinfo.name = desc->name;
  140. pinfo.label = desc->label;
  141. pinfo.maker = desc->maker;
  142. pinfo.category = getPluginCategoryAsString(desc->category);
  143. pinfo.audioIns = desc->audioIns;
  144. pinfo.audioOuts = desc->audioOuts;
  145. pinfo.cvIns = desc->cvIns;
  146. pinfo.cvOuts = desc->cvOuts;
  147. pinfo.midiIns = desc->midiIns;
  148. pinfo.midiOuts = desc->midiOuts;
  149. pinfo.parametersIns = desc->parameterIns;
  150. pinfo.parametersOuts = desc->parameterOuts;
  151. switch (ptype)
  152. {
  153. case PLUGIN_LV2:
  154. {
  155. QString label(desc->label);
  156. pinfo.filename = label.split(CARLA_OS_SEP).first();
  157. pinfo.label = label.section(CARLA_OS_SEP, 1);
  158. }
  159. break;
  160. case PLUGIN_SFZ:
  161. pinfo.filename = pinfo.label;
  162. pinfo.label = pinfo.name;
  163. break;
  164. default:
  165. break;
  166. }
  167. return pinfo;
  168. }
  169. uint reAddInternalHelper(QSafePluginListSettings& settingsDB, const PluginType ptype, const char* const path)
  170. {
  171. QString ptypeStr, ptypeStrTr;
  172. switch (ptype)
  173. {
  174. case PLUGIN_INTERNAL:
  175. ptypeStr = "Internal";
  176. ptypeStrTr = "Internal"; // self.tr("Internal")
  177. break;
  178. case PLUGIN_LV2:
  179. ptypeStr = "LV2";
  180. ptypeStrTr = ptypeStr;
  181. break;
  182. case PLUGIN_AU:
  183. ptypeStr = "AU";
  184. ptypeStrTr = ptypeStr;
  185. break;
  186. case PLUGIN_SFZ:
  187. ptypeStr = "SFZ";
  188. ptypeStrTr = ptypeStr;
  189. break;
  190. // TODO(jsfx) what to do here?
  191. default:
  192. return 0;
  193. }
  194. QPluginInfoList plugins = settingsDB.valuePluginInfoList("Plugins/" + ptypeStr);
  195. uint pluginCount = settingsDB.valueUInt("PluginCount/" + ptypeStr, 0);
  196. if (ptype == PLUGIN_AU)
  197. carla_juce_init();
  198. const uint pluginCountNew = carla_get_cached_plugin_count(ptype, path);
  199. if (pluginCountNew != pluginCount || plugins.size() != pluginCount ||
  200. (plugins.size() > 0 && plugins[0].API != PLUGIN_QUERY_API_VERSION))
  201. {
  202. plugins.clear();
  203. pluginCount = pluginCountNew;
  204. QApplication::instance()->processEvents(QEventLoop::ExcludeUserInputEvents, 50);
  205. if (ptype == PLUGIN_AU)
  206. carla_juce_idle();
  207. for (uint i=0; i<pluginCountNew; ++i)
  208. {
  209. const CarlaCachedPluginInfo* const descInfo = carla_get_cached_plugin_info(ptype, i);
  210. if (descInfo == nullptr)
  211. continue;
  212. const PluginInfo info = checkPluginCached(descInfo, ptype);
  213. plugins.append(info);
  214. if ((i % 50) == 0)
  215. {
  216. QApplication::instance()->processEvents(QEventLoop::ExcludeUserInputEvents, 50);
  217. if (ptype == PLUGIN_AU)
  218. carla_juce_idle();
  219. }
  220. }
  221. settingsDB.setValue("Plugins/" + ptypeStr, plugins);
  222. settingsDB.setValue("PluginCount/" + ptypeStr, pluginCount);
  223. }
  224. if (ptype == PLUGIN_AU)
  225. carla_juce_cleanup();
  226. // prepare rows in advance
  227. ui.tableWidget->setRowCount(fLastTableIndex + plugins.size());
  228. // for plugin in plugins:
  229. // self._addPluginToTable(plugin, ptypeStrTr)
  230. return pluginCount;
  231. }
  232. void reAddPlugins()
  233. {
  234. QSafePluginListSettings settingsDB("falkTX", "CarlaPlugins5");
  235. fLastTableIndex = 0;
  236. ui.tableWidget->setSortingEnabled(false);
  237. ui.tableWidget->clearContents();
  238. QString LV2_PATH;
  239. {
  240. const QSafeSettings settings("falkTX", "Carla2");
  241. // LV2_PATH = splitter.join()
  242. // settings.valueStringList(CARLA_KEY_PATHS_LV2, CARLA_DEFAULT_LV2_PATH);
  243. }
  244. // ------------------------------------------------------------------------------------------------------------
  245. // plugins handled through backend
  246. const uint internalCount = reAddInternalHelper(settingsDB, PLUGIN_INTERNAL, "");
  247. const uint lv2Count = reAddInternalHelper(settingsDB, PLUGIN_LV2, LV2_PATH.toUtf8());
  248. #ifdef CARLA_OS_MAC
  249. const uint auCount = reAddInternalHelper(settingsDB, PLUGIN_AU, "");
  250. #else
  251. const uint auCount = 0;
  252. #endif
  253. // ------------------------------------------------------------------------------------------------------------
  254. // LADSPA
  255. QStringList ladspaPlugins;
  256. ladspaPlugins << settingsDB.valueStringList("Plugins/LADSPA_native");
  257. ladspaPlugins << settingsDB.valueStringList("Plugins/LADSPA_posix32");
  258. ladspaPlugins << settingsDB.valueStringList("Plugins/LADSPA_posix64");
  259. ladspaPlugins << settingsDB.valueStringList("Plugins/LADSPA_win32");
  260. ladspaPlugins << settingsDB.valueStringList("Plugins/LADSPA_win64");
  261. }
  262. };
  263. PluginListDialog::PluginListDialog(QWidget* const parent, const HostSettings& hostSettings)
  264. : QDialog(parent),
  265. self(Self::create())
  266. {
  267. self.ui.setupUi(this);
  268. self.hostSettings = hostSettings;
  269. // ----------------------------------------------------------------------------------------------------------------
  270. // Internal stuff
  271. self.fLastTableIndex = 0;
  272. self.fRetPlugin = {};
  273. self.fRealParent = parent;
  274. self.fFavoritePlugins.clear();
  275. self.fFavoritePluginsChanged = false;
  276. self.fTrYes = tr("Yes");
  277. self.fTrNo = tr("No");
  278. self.fTrNative = tr("Native");
  279. // ----------------------------------------------------------------------------------------------------------------
  280. // Set-up GUI
  281. self.ui.b_add->setEnabled(false);
  282. addAction(self.ui.act_focus_search);
  283. // TODO
  284. // self.ui.act_focus_search.triggered.connect(self.slot_focusSearchFieldAndSelectAll);
  285. #if BINARY_NATIVE == BINARY_POSIX32 || BINARY_NATIVE == BINARY_WIN32
  286. self.ui.ch_bridged->setText(tr("Bridged (64bit)"));
  287. #else
  288. self.ui.ch_bridged->setText(tr("Bridged (32bit)"));
  289. #endif
  290. #if !(defined(CARLA_OS_LINUX) || defined(CARLA_OS_MAC))
  291. self.ui.ch_bridged_wine->setChecked(false);
  292. self.ui.ch_bridged_wine->setEnabled(false);
  293. #endif
  294. #ifdef CARLA_OS_MAC
  295. setWindowModality(Qt::WindowModal);
  296. #else
  297. self.ui.ch_au->setChecked(false);
  298. self.ui.ch_au->setEnabled(false);
  299. self.ui.ch_au->setVisible(false);
  300. #endif
  301. self.ui.tab_info->tabBar()->hide();
  302. self.ui.tab_reqs->tabBar()->hide();
  303. // FIXME, why /2 needed?
  304. self.ui.tab_info->setMinimumWidth(self.ui.la_id->width()/2 +
  305. fontMetricsHorizontalAdvance(self.ui.l_id->fontMetrics(), "9999999999") + 6*3);
  306. setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
  307. // ----------------------------------------------------------------------------------------------------------------
  308. // Load settings
  309. loadSettings();
  310. // ----------------------------------------------------------------------------------------------------------------
  311. // Disable bridges if not enabled in settings
  312. // NOTE: We Assume win32 carla build will not run win64 plugins
  313. // if (WINDOWS and not kIs64bit) or not host.showPluginBridges:
  314. // self.ui.ch_native.setChecked(True)
  315. // self.ui.ch_native.setEnabled(False)
  316. // self.ui.ch_native.setVisible(True)
  317. // self.ui.ch_bridged.setChecked(False)
  318. // self.ui.ch_bridged.setEnabled(False)
  319. // self.ui.ch_bridged.setVisible(False)
  320. // self.ui.ch_bridged_wine.setChecked(False)
  321. // self.ui.ch_bridged_wine.setEnabled(False)
  322. // self.ui.ch_bridged_wine.setVisible(False)
  323. //
  324. // elif not host.showWineBridges:
  325. // self.ui.ch_bridged_wine.setChecked(False)
  326. // self.ui.ch_bridged_wine.setEnabled(False)
  327. // self.ui.ch_bridged_wine.setVisible(False)
  328. // ----------------------------------------------------------------------------------------------------------------
  329. // Set-up Icons
  330. if (hostSettings.useSystemIcons)
  331. {
  332. // self.ui.b_add.setIcon(getIcon('list-add', 16, 'svgz'))
  333. // self.ui.b_cancel.setIcon(getIcon('dialog-cancel', 16, 'svgz'))
  334. // self.ui.b_clear_filters.setIcon(getIcon('edit-clear', 16, 'svgz'))
  335. // self.ui.b_refresh.setIcon(getIcon('view-refresh', 16, 'svgz'))
  336. QTableWidgetItem* const hhi = self.ui.tableWidget->horizontalHeaderItem(self.TABLEWIDGET_ITEM_FAVORITE);
  337. // hhi.setIcon(getIcon('bookmarks', 16, 'svgz'))
  338. }
  339. // ----------------------------------------------------------------------------------------------------------------
  340. // Set-up connections
  341. // self.finished.connect(self.slot_saveSettings)
  342. // self.ui.b_add.clicked.connect(self.slot_addPlugin)
  343. // self.ui.b_cancel.clicked.connect(self.reject)
  344. // self.ui.b_refresh.clicked.connect(self.slot_refreshPlugins)
  345. // self.ui.b_clear_filters.clicked.connect(self.slot_clearFilters)
  346. // self.ui.lineEdit.textChanged.connect(self.slot_checkFilters)
  347. // self.ui.tableWidget.currentCellChanged.connect(self.slot_checkPlugin)
  348. // self.ui.tableWidget.cellClicked.connect(self.slot_cellClicked)
  349. // self.ui.tableWidget.cellDoubleClicked.connect(self.slot_cellDoubleClicked)
  350. //
  351. // self.ui.ch_internal.clicked.connect(self.slot_checkFilters)
  352. // self.ui.ch_ladspa.clicked.connect(self.slot_checkFilters)
  353. // self.ui.ch_dssi.clicked.connect(self.slot_checkFilters)
  354. // self.ui.ch_lv2.clicked.connect(self.slot_checkFilters)
  355. // self.ui.ch_vst.clicked.connect(self.slot_checkFilters)
  356. // self.ui.ch_vst3.clicked.connect(self.slot_checkFilters)
  357. // self.ui.ch_clap.clicked.connect(self.slot_checkFilters)
  358. // self.ui.ch_au.clicked.connect(self.slot_checkFilters)
  359. // self.ui.ch_jsfx.clicked.connect(self.slot_checkFilters)
  360. // self.ui.ch_kits.clicked.connect(self.slot_checkFilters)
  361. // self.ui.ch_effects.clicked.connect(self.slot_checkFilters)
  362. // self.ui.ch_instruments.clicked.connect(self.slot_checkFilters)
  363. // self.ui.ch_midi.clicked.connect(self.slot_checkFilters)
  364. // self.ui.ch_other.clicked.connect(self.slot_checkFilters)
  365. // self.ui.ch_native.clicked.connect(self.slot_checkFilters)
  366. // self.ui.ch_bridged.clicked.connect(self.slot_checkFilters)
  367. // self.ui.ch_bridged_wine.clicked.connect(self.slot_checkFilters)
  368. // self.ui.ch_favorites.clicked.connect(self.slot_checkFilters)
  369. // self.ui.ch_rtsafe.clicked.connect(self.slot_checkFilters)
  370. // self.ui.ch_cv.clicked.connect(self.slot_checkFilters)
  371. // self.ui.ch_gui.clicked.connect(self.slot_checkFilters)
  372. // self.ui.ch_inline_display.clicked.connect(self.slot_checkFilters)
  373. // self.ui.ch_stereo.clicked.connect(self.slot_checkFilters)
  374. // self.ui.ch_cat_all.clicked.connect(self.slot_checkFiltersCategoryAll)
  375. // self.ui.ch_cat_delay.clicked.connect(self.slot_checkFiltersCategorySpecific)
  376. // self.ui.ch_cat_distortion.clicked.connect(self.slot_checkFiltersCategorySpecific)
  377. // self.ui.ch_cat_dynamics.clicked.connect(self.slot_checkFiltersCategorySpecific)
  378. // self.ui.ch_cat_eq.clicked.connect(self.slot_checkFiltersCategorySpecific)
  379. // self.ui.ch_cat_filter.clicked.connect(self.slot_checkFiltersCategorySpecific)
  380. // self.ui.ch_cat_modulator.clicked.connect(self.slot_checkFiltersCategorySpecific)
  381. // self.ui.ch_cat_synth.clicked.connect(self.slot_checkFiltersCategorySpecific)
  382. // self.ui.ch_cat_utility.clicked.connect(self.slot_checkFiltersCategorySpecific)
  383. // self.ui.ch_cat_other.clicked.connect(self.slot_checkFiltersCategorySpecific)
  384. // ----------------------------------------------------------------------------------------------------------------
  385. // Post-connect setup
  386. self.reAddPlugins();
  387. slot_focusSearchFieldAndSelectAll();
  388. }
  389. PluginListDialog::~PluginListDialog()
  390. {
  391. delete &self;
  392. }
  393. // --------------------------------------------------------------------------------------------------------------------
  394. // public methods
  395. // --------------------------------------------------------------------------------------------------------------------
  396. // protected methods
  397. void PluginListDialog::showEvent(QShowEvent* const event)
  398. {
  399. slot_focusSearchFieldAndSelectAll();
  400. QDialog::showEvent(event);
  401. }
  402. // --------------------------------------------------------------------------------------------------------------------
  403. // private methods
  404. void PluginListDialog::loadSettings()
  405. {
  406. const QSafeSettings settings("falkTX", "CarlaDatabase2");
  407. self.fFavoritePlugins = settings.valueStringList("PluginDatabase/Favorites");
  408. self.fFavoritePluginsChanged = false;
  409. restoreGeometry(settings.valueByteArray("PluginDatabase/Geometry"));
  410. self.ui.ch_effects->setChecked(settings.valueBool("PluginDatabase/ShowEffects", true));
  411. self.ui.ch_instruments->setChecked(settings.valueBool("PluginDatabase/ShowInstruments", true));
  412. self.ui.ch_midi->setChecked(settings.valueBool("PluginDatabase/ShowMIDI", true));
  413. self.ui.ch_other->setChecked(settings.valueBool("PluginDatabase/ShowOther", true));
  414. self.ui.ch_internal->setChecked(settings.valueBool("PluginDatabase/ShowInternal", true));
  415. self.ui.ch_ladspa->setChecked(settings.valueBool("PluginDatabase/ShowLADSPA", true));
  416. self.ui.ch_dssi->setChecked(settings.valueBool("PluginDatabase/ShowDSSI", true));
  417. self.ui.ch_lv2->setChecked(settings.valueBool("PluginDatabase/ShowLV2", true));
  418. self.ui.ch_vst->setChecked(settings.valueBool("PluginDatabase/ShowVST2", true));
  419. self.ui.ch_vst3->setChecked(settings.valueBool("PluginDatabase/ShowVST3", true));
  420. self.ui.ch_clap->setChecked(settings.valueBool("PluginDatabase/ShowCLAP", true));
  421. #ifdef CARLA_OS_MAC
  422. self.ui.ch_au->setChecked(settings.valueBool("PluginDatabase/ShowAU", true));
  423. #endif
  424. self.ui.ch_jsfx->setChecked(settings.valueBool("PluginDatabase/ShowJSFX", true));
  425. self.ui.ch_kits->setChecked(settings.valueBool("PluginDatabase/ShowKits", true));
  426. self.ui.ch_native->setChecked(settings.valueBool("PluginDatabase/ShowNative", true));
  427. self.ui.ch_bridged->setChecked(settings.valueBool("PluginDatabase/ShowBridged", true));
  428. self.ui.ch_bridged_wine->setChecked(settings.valueBool("PluginDatabase/ShowBridgedWine", true));
  429. self.ui.ch_favorites->setChecked(settings.valueBool("PluginDatabase/ShowFavorites", false));
  430. self.ui.ch_rtsafe->setChecked(settings.valueBool("PluginDatabase/ShowRtSafe", false));
  431. self.ui.ch_cv->setChecked(settings.valueBool("PluginDatabase/ShowHasCV", false));
  432. self.ui.ch_gui->setChecked(settings.valueBool("PluginDatabase/ShowHasGUI", false));
  433. self.ui.ch_inline_display->setChecked(settings.valueBool("PluginDatabase/ShowHasInlineDisplay", false));
  434. self.ui.ch_stereo->setChecked(settings.valueBool("PluginDatabase/ShowStereoOnly", false));
  435. self.ui.lineEdit->setText(settings.valueString("PluginDatabase/SearchText", ""));
  436. QString categoryhash = settings.valueString("PluginDatabase/ShowCategory", "all");
  437. if (categoryhash == "all" or categoryhash.length() < 2)
  438. {
  439. self.ui.ch_cat_all->setChecked(true);
  440. self.ui.ch_cat_delay->setChecked(false);
  441. self.ui.ch_cat_distortion->setChecked(false);
  442. self.ui.ch_cat_dynamics->setChecked(false);
  443. self.ui.ch_cat_eq->setChecked(false);
  444. self.ui.ch_cat_filter->setChecked(false);
  445. self.ui.ch_cat_modulator->setChecked(false);
  446. self.ui.ch_cat_synth->setChecked(false);
  447. self.ui.ch_cat_utility->setChecked(false);
  448. self.ui.ch_cat_other->setChecked(false);
  449. }
  450. else
  451. {
  452. self.ui.ch_cat_all->setChecked(false);
  453. self.ui.ch_cat_delay->setChecked(categoryhash.contains(":delay:"));
  454. self.ui.ch_cat_distortion->setChecked(categoryhash.contains(":distortion:"));
  455. self.ui.ch_cat_dynamics->setChecked(categoryhash.contains(":dynamics:"));
  456. self.ui.ch_cat_eq->setChecked(categoryhash.contains(":eq:"));
  457. self.ui.ch_cat_filter->setChecked(categoryhash.contains(":filter:"));
  458. self.ui.ch_cat_modulator->setChecked(categoryhash.contains(":modulator:"));
  459. self.ui.ch_cat_synth->setChecked(categoryhash.contains(":synth:"));
  460. self.ui.ch_cat_utility->setChecked(categoryhash.contains(":utility:"));
  461. self.ui.ch_cat_other->setChecked(categoryhash.contains(":other:"));
  462. }
  463. QByteArray tableGeometry = settings.valueByteArray("PluginDatabase/TableGeometry_6");
  464. QHeaderView* const horizontalHeader = self.ui.tableWidget->horizontalHeader();
  465. if (! tableGeometry.isNull())
  466. {
  467. horizontalHeader->restoreState(tableGeometry);
  468. }
  469. else
  470. {
  471. horizontalHeader->setSectionResizeMode(self.TABLEWIDGET_ITEM_FAVORITE, QHeaderView::Fixed);
  472. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_FAVORITE, 24);
  473. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_NAME, 250);
  474. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_LABEL, 200);
  475. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_MAKER, 150);
  476. self.ui.tableWidget->sortByColumn(self.TABLEWIDGET_ITEM_NAME, Qt::AscendingOrder);
  477. }
  478. }
  479. // -----------------------------------------------------------------------------------------------------------------
  480. // private slots
  481. void PluginListDialog::slot_cellClicked(int row, int column)
  482. {
  483. if (column == self.TABLEWIDGET_ITEM_FAVORITE)
  484. {
  485. QTableWidgetItem* const widget = self.ui.tableWidget->item(row, self.TABLEWIDGET_ITEM_FAVORITE);
  486. // plugin = self.ui.tableWidget.item(row, self.TABLEWIDGET_ITEM_NAME).data(Qt.UserRole+1);
  487. // plugin = self._createFavoritePluginDict(plugin);
  488. if (widget->checkState() == Qt::Checked)
  489. {
  490. // if (not plugin in self.fFavoritePlugins)
  491. // {
  492. // self.fFavoritePlugins.append(plugin);
  493. // self.fFavoritePluginsChanged = true;
  494. // }
  495. }
  496. else
  497. {
  498. // try:
  499. // self.fFavoritePlugins.remove(plugin);
  500. // self.fFavoritePluginsChanged = True;
  501. // except ValueError:
  502. // pass
  503. }
  504. }
  505. }
  506. void PluginListDialog::slot_cellDoubleClicked(int, int column)
  507. {
  508. if (column != self.TABLEWIDGET_ITEM_FAVORITE)
  509. slot_addPlugin();
  510. }
  511. void PluginListDialog::slot_focusSearchFieldAndSelectAll()
  512. {
  513. self.ui.lineEdit->setFocus();
  514. self.ui.lineEdit->selectAll();
  515. }
  516. void PluginListDialog::slot_addPlugin()
  517. {
  518. if (self.ui.tableWidget->currentRow() >= 0)
  519. {
  520. // self.fRetPlugin = self.ui.tableWidget->item(self.ui.tableWidget->currentRow(),
  521. // self.TABLEWIDGET_ITEM_NAME).data(Qt.UserRole+1);
  522. accept();
  523. }
  524. else
  525. {
  526. reject();
  527. }
  528. }
  529. void PluginListDialog::slot_checkPlugin(int row)
  530. {
  531. if (row >= 0)
  532. {
  533. self.ui.b_add->setEnabled(true);
  534. // auto plugin = self.ui.tableWidget.item(self.ui.tableWidget.currentRow(),
  535. // self.TABLEWIDGET_ITEM_NAME).data(Qt::UserRole+1);
  536. //
  537. // const bool isSynth = plugin['hints'] & PLUGIN_IS_SYNTH;
  538. // const bool isEffect = plugin['audio.ins'] > 0 && plugin['audio.outs'] > 0 && !isSynth;
  539. // const bool isMidi = plugin['audio.ins'] == 0 &&
  540. // plugin['audio.outs'] == 0 &&
  541. // plugin['midi.ins'] > 0 < plugin['midi.outs'];
  542. // // const bool isKit = plugin['type'] in (PLUGIN_SF2, PLUGIN_SFZ);
  543. // // const bool isOther = ! (isEffect || isSynth || isMidi || isKit);
  544. QString ptype;
  545. // /**/ if (isSynth)
  546. // ptype = "Instrument";
  547. // else if (isEffect)
  548. // ptype = "Effect";
  549. // else if (isMidi)
  550. // ptype = "MIDI Plugin";
  551. // else
  552. // ptype = "Other";
  553. QString parch;
  554. // /**/ if (plugin['build'] == BINARY_NATIVE)
  555. // parch = self.fTrNative;
  556. // else if (plugin['build'] == BINARY_POSIX32)
  557. // parch = "posix32";
  558. // else if (plugin['build'] == BINARY_POSIX64)
  559. // parch = "posix64";
  560. // else if (plugin['build'] == BINARY_WIN32)
  561. // parch = "win32";
  562. // else if (plugin['build'] == BINARY_WIN64)
  563. // parch = "win64";
  564. // else if (plugin['build'] == BINARY_OTHER)
  565. // parch = tr("Other");
  566. // else if (plugin['build'] == BINARY_WIN32)
  567. // parch = tr("Unknown");
  568. // self.ui.l_format->setText(getPluginTypeAsString(plugin['type']));
  569. self.ui.l_type->setText(ptype);
  570. self.ui.l_arch->setText(parch);
  571. // self.ui.l_id->setText(str(plugin['uniqueId']));
  572. // self.ui.l_ains->setText(str(plugin['audio.ins']));
  573. // self.ui.l_aouts->setText(str(plugin['audio.outs']));
  574. // self.ui.l_cvins->setText(str(plugin['cv.ins']));
  575. // self.ui.l_cvouts->setText(str(plugin['cv.outs']));
  576. // self.ui.l_mins->setText(str(plugin['midi.ins']));
  577. // self.ui.l_mouts->setText(str(plugin['midi.outs']));
  578. // self.ui.l_pins->setText(str(plugin['parameters.ins']));
  579. // self.ui.l_pouts->setText(str(plugin['parameters.outs']));
  580. // self.ui.l_gui->setText(plugin['hints'] & PLUGIN_HAS_CUSTOM_UI ? self.fTrYes : self.fTrNo);
  581. // self.ui.l_idisp->setText(plugin['hints'] & PLUGIN_HAS_INLINE_DISPLAY ? self.fTrYes : self.fTrNo);
  582. // self.ui.l_bridged->setText(plugin['hints'] & PLUGIN_IS_BRIDGE ? self.fTrYes : self.fTrNo);
  583. // self.ui.l_synth->setText(isSynth ? self.fTrYes : self.fTrNo);
  584. }
  585. else
  586. {
  587. self.ui.b_add->setEnabled(false);
  588. self.ui.l_format->setText("---");
  589. self.ui.l_type->setText("---");
  590. self.ui.l_arch->setText("---");
  591. self.ui.l_id->setText("---");
  592. self.ui.l_ains->setText("---");
  593. self.ui.l_aouts->setText("---");
  594. self.ui.l_cvins->setText("---");
  595. self.ui.l_cvouts->setText("---");
  596. self.ui.l_mins->setText("---");
  597. self.ui.l_mouts->setText("---");
  598. self.ui.l_pins->setText("---");
  599. self.ui.l_pouts->setText("---");
  600. self.ui.l_gui->setText("---");
  601. self.ui.l_idisp->setText("---");
  602. self.ui.l_bridged->setText("---");
  603. self.ui.l_synth->setText("---");
  604. }
  605. }
  606. void PluginListDialog::slot_checkFilters()
  607. {
  608. // TODO
  609. }
  610. void PluginListDialog::slot_checkFiltersCategoryAll(const bool clicked)
  611. {
  612. const bool notClicked = !clicked;
  613. self.ui.ch_cat_delay->setChecked(notClicked);
  614. self.ui.ch_cat_distortion->setChecked(notClicked);
  615. self.ui.ch_cat_dynamics->setChecked(notClicked);
  616. self.ui.ch_cat_eq->setChecked(notClicked);
  617. self.ui.ch_cat_filter->setChecked(notClicked);
  618. self.ui.ch_cat_modulator->setChecked(notClicked);
  619. self.ui.ch_cat_synth->setChecked(notClicked);
  620. self.ui.ch_cat_utility->setChecked(notClicked);
  621. self.ui.ch_cat_other->setChecked(notClicked);
  622. slot_checkFilters();
  623. }
  624. void PluginListDialog::slot_checkFiltersCategorySpecific(bool clicked)
  625. {
  626. if (clicked)
  627. {
  628. self.ui.ch_cat_all->setChecked(false);
  629. }
  630. else if (! (self.ui.ch_cat_delay->isChecked() ||
  631. self.ui.ch_cat_distortion->isChecked() ||
  632. self.ui.ch_cat_dynamics->isChecked() ||
  633. self.ui.ch_cat_eq->isChecked() ||
  634. self.ui.ch_cat_filter->isChecked() ||
  635. self.ui.ch_cat_modulator->isChecked() ||
  636. self.ui.ch_cat_synth->isChecked() ||
  637. self.ui.ch_cat_utility->isChecked() ||
  638. self.ui.ch_cat_other->isChecked()))
  639. {
  640. self.ui.ch_cat_all->setChecked(true);
  641. }
  642. slot_checkFilters();
  643. }
  644. void PluginListDialog::slot_refreshPlugins()
  645. {
  646. // if (PluginRefreshW(this, self.hostSettings, self.hasLoadedLv2Plugins).exec())
  647. // reAddPlugins();
  648. }
  649. void PluginListDialog::slot_clearFilters()
  650. {
  651. blockSignals(true);
  652. self.ui.ch_internal->setChecked(true);
  653. self.ui.ch_ladspa->setChecked(true);
  654. self.ui.ch_dssi->setChecked(true);
  655. self.ui.ch_lv2->setChecked(true);
  656. self.ui.ch_vst->setChecked(true);
  657. self.ui.ch_vst3->setChecked(true);
  658. self.ui.ch_clap->setChecked(true);
  659. self.ui.ch_jsfx->setChecked(true);
  660. self.ui.ch_kits->setChecked(true);
  661. self.ui.ch_instruments->setChecked(true);
  662. self.ui.ch_effects->setChecked(true);
  663. self.ui.ch_midi->setChecked(true);
  664. self.ui.ch_other->setChecked(true);
  665. self.ui.ch_native->setChecked(true);
  666. self.ui.ch_bridged->setChecked(false);
  667. self.ui.ch_bridged_wine->setChecked(false);
  668. self.ui.ch_favorites->setChecked(false);
  669. self.ui.ch_rtsafe->setChecked(false);
  670. self.ui.ch_stereo->setChecked(false);
  671. self.ui.ch_cv->setChecked(false);
  672. self.ui.ch_gui->setChecked(false);
  673. self.ui.ch_inline_display->setChecked(false);
  674. if (self.ui.ch_au->isEnabled())
  675. self.ui.ch_au->setChecked(true);
  676. self.ui.ch_cat_all->setChecked(true);
  677. self.ui.ch_cat_delay->setChecked(false);
  678. self.ui.ch_cat_distortion->setChecked(false);
  679. self.ui.ch_cat_dynamics->setChecked(false);
  680. self.ui.ch_cat_eq->setChecked(false);
  681. self.ui.ch_cat_filter->setChecked(false);
  682. self.ui.ch_cat_modulator->setChecked(false);
  683. self.ui.ch_cat_synth->setChecked(false);
  684. self.ui.ch_cat_utility->setChecked(false);
  685. self.ui.ch_cat_other->setChecked(false);
  686. self.ui.lineEdit->clear();
  687. blockSignals(false);
  688. slot_checkFilters();
  689. }
  690. // --------------------------------------------------------------------------------------------------------------------
  691. void PluginListDialog::slot_saveSettings()
  692. {
  693. QSafeSettings settings("falkTX", "CarlaDatabase2");
  694. settings.setValue("PluginDatabase/Geometry", saveGeometry());
  695. settings.setValue("PluginDatabase/TableGeometry_6", self.ui.tableWidget->horizontalHeader()->saveState());
  696. settings.setValue("PluginDatabase/ShowEffects", self.ui.ch_effects->isChecked());
  697. settings.setValue("PluginDatabase/ShowInstruments", self.ui.ch_instruments->isChecked());
  698. settings.setValue("PluginDatabase/ShowMIDI", self.ui.ch_midi->isChecked());
  699. settings.setValue("PluginDatabase/ShowOther", self.ui.ch_other->isChecked());
  700. settings.setValue("PluginDatabase/ShowInternal", self.ui.ch_internal->isChecked());
  701. settings.setValue("PluginDatabase/ShowLADSPA", self.ui.ch_ladspa->isChecked());
  702. settings.setValue("PluginDatabase/ShowDSSI", self.ui.ch_dssi->isChecked());
  703. settings.setValue("PluginDatabase/ShowLV2", self.ui.ch_lv2->isChecked());
  704. settings.setValue("PluginDatabase/ShowVST2", self.ui.ch_vst->isChecked());
  705. settings.setValue("PluginDatabase/ShowVST3", self.ui.ch_vst3->isChecked());
  706. settings.setValue("PluginDatabase/ShowCLAP", self.ui.ch_clap->isChecked());
  707. settings.setValue("PluginDatabase/ShowAU", self.ui.ch_au->isChecked());
  708. settings.setValue("PluginDatabase/ShowJSFX", self.ui.ch_jsfx->isChecked());
  709. settings.setValue("PluginDatabase/ShowKits", self.ui.ch_kits->isChecked());
  710. settings.setValue("PluginDatabase/ShowNative", self.ui.ch_native->isChecked());
  711. settings.setValue("PluginDatabase/ShowBridged", self.ui.ch_bridged->isChecked());
  712. settings.setValue("PluginDatabase/ShowBridgedWine", self.ui.ch_bridged_wine->isChecked());
  713. settings.setValue("PluginDatabase/ShowFavorites", self.ui.ch_favorites->isChecked());
  714. settings.setValue("PluginDatabase/ShowRtSafe", self.ui.ch_rtsafe->isChecked());
  715. settings.setValue("PluginDatabase/ShowHasCV", self.ui.ch_cv->isChecked());
  716. settings.setValue("PluginDatabase/ShowHasGUI", self.ui.ch_gui->isChecked());
  717. settings.setValue("PluginDatabase/ShowHasInlineDisplay", self.ui.ch_inline_display->isChecked());
  718. settings.setValue("PluginDatabase/ShowStereoOnly", self.ui.ch_stereo->isChecked());
  719. settings.setValue("PluginDatabase/SearchText", self.ui.lineEdit->text());
  720. if (self.ui.ch_cat_all->isChecked())
  721. {
  722. settings.setValue("PluginDatabase/ShowCategory", "all");
  723. }
  724. else
  725. {
  726. QCarlaString categoryhash;
  727. if (self.ui.ch_cat_delay->isChecked())
  728. categoryhash += ":delay";
  729. if (self.ui.ch_cat_distortion->isChecked())
  730. categoryhash += ":distortion";
  731. if (self.ui.ch_cat_dynamics->isChecked())
  732. categoryhash += ":dynamics";
  733. if (self.ui.ch_cat_eq->isChecked())
  734. categoryhash += ":eq";
  735. if (self.ui.ch_cat_filter->isChecked())
  736. categoryhash += ":filter";
  737. if (self.ui.ch_cat_modulator->isChecked())
  738. categoryhash += ":modulator";
  739. if (self.ui.ch_cat_synth->isChecked())
  740. categoryhash += ":synth";
  741. if (self.ui.ch_cat_utility->isChecked())
  742. categoryhash += ":utility";
  743. if (self.ui.ch_cat_other->isChecked())
  744. categoryhash += ":other";
  745. if (categoryhash.isNotEmpty())
  746. categoryhash += ":";
  747. settings.setValue("PluginDatabase/ShowCategory", categoryhash);
  748. }
  749. if (self.fFavoritePluginsChanged)
  750. settings.setValue("PluginDatabase/Favorites", self.fFavoritePlugins);
  751. }
  752. // --------------------------------------------------------------------------------------------------------------------
  753. PluginListDialogResults*
  754. carla_frontend_createAndExecPluginListDialog(void* const parent/*, const HostSettings& hostSettings*/)
  755. {
  756. const HostSettings hostSettings = {};
  757. PluginListDialog gui(reinterpret_cast<QWidget*>(parent), hostSettings);
  758. if (gui.exec())
  759. {
  760. static PluginListDialogResults ret = {};
  761. static CarlaString retBinary;
  762. // TODO
  763. return &ret;
  764. }
  765. return nullptr;
  766. }
  767. // --------------------------------------------------------------------------------------------------------------------