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.

1845 lines
72KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla plugin database code
  4. # Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation; either version 2 of
  9. # the License, or any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. # ----------------------------------------------------------------------------------------------------------------------
  18. # Imports (Config)
  19. from carla_config import *
  20. # ----------------------------------------------------------------------------------------------------------------------
  21. # Imports (Global)
  22. from copy import deepcopy
  23. from subprocess import Popen, PIPE
  24. if config_UseQt5:
  25. from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QEventLoop, QThread, QSettings
  26. from PyQt5.QtWidgets import QApplication, QDialog, QDialogButtonBox, QTableWidgetItem
  27. else:
  28. from PyQt4.QtCore import pyqtSignal, pyqtSlot, Qt, QEventLoop, QThread, QSettings
  29. from PyQt4.QtGui import QApplication, QDialog, QDialogButtonBox, QTableWidgetItem
  30. # ----------------------------------------------------------------------------------------------------------------------
  31. # Imports (Custom)
  32. import ui_carla_add_jack
  33. import ui_carla_database
  34. import ui_carla_refresh
  35. from carla_shared import *
  36. # ----------------------------------------------------------------------------------------------------------------------
  37. # Try Import LADSPA-RDF
  38. if WINDOWS:
  39. haveLRDF = False
  40. elif not CXFREEZE:
  41. try:
  42. import ladspa_rdf
  43. import json
  44. haveLRDF = True
  45. except:
  46. qWarning("LRDF Support not available (LADSPA-RDF will be disabled)")
  47. haveLRDF = False
  48. else:
  49. qWarning("LRDF Support disabled for static build (LADSPA-RDF will be disabled)")
  50. haveLRDF = False
  51. # ----------------------------------------------------------------------------------------------------------------------
  52. # Set LADSPA-RDF Path
  53. if haveLRDF and readEnvVars:
  54. LADSPA_RDF_PATH_env = os.getenv("LADSPA_RDF_PATH")
  55. if LADSPA_RDF_PATH_env:
  56. try:
  57. ladspa_rdf.set_rdf_path(LADSPA_RDF_PATH_env.split(splitter))
  58. except:
  59. pass
  60. del LADSPA_RDF_PATH_env
  61. # ----------------------------------------------------------------------------------------------------------------------
  62. # Plugin Query (helper functions)
  63. def findBinaries(binPath, OS):
  64. binaries = []
  65. if OS == "WINDOWS":
  66. extensions = (".dll",)
  67. elif OS == "MACOS":
  68. extensions = (".dylib", ".so")
  69. else:
  70. extensions = (".so",)
  71. for root, dirs, files in os.walk(binPath):
  72. for name in [name for name in files if name.lower().endswith(extensions)]:
  73. binaries.append(os.path.join(root, name))
  74. return binaries
  75. def findLV2Bundles(bundlePath):
  76. bundles = []
  77. for root, dirs, files in os.walk(bundlePath, followlinks=True):
  78. if root == bundlePath: continue
  79. if os.path.exists(os.path.join(root, "manifest.ttl")):
  80. bundles.append(root)
  81. return bundles
  82. def findMacVSTBundles(bundlePath):
  83. bundles = []
  84. for root, dirs, files in os.walk(bundlePath, followlinks=True):
  85. #if root == bundlePath: continue # FIXME
  86. for name in [name for name in dirs if name.lower().endswith(".vst")]:
  87. bundles.append(os.path.join(root, name))
  88. return bundles
  89. def findFilenames(filePath, stype):
  90. filenames = []
  91. if stype == "sf2":
  92. extensions = (".sf2",".sf3",)
  93. else:
  94. return []
  95. for root, dirs, files in os.walk(filePath):
  96. for name in [name for name in files if name.lower().endswith(extensions)]:
  97. filenames.append(os.path.join(root, name))
  98. return filenames
  99. # ----------------------------------------------------------------------------------------------------------------------
  100. # Plugin Query
  101. PLUGIN_QUERY_API_VERSION = 8
  102. PyPluginInfo = {
  103. 'API': PLUGIN_QUERY_API_VERSION,
  104. 'valid': False,
  105. 'build': BINARY_NONE,
  106. 'type': PLUGIN_NONE,
  107. 'hints': 0x0,
  108. 'filename': "",
  109. 'name': "",
  110. 'label': "",
  111. 'maker': "",
  112. 'uniqueId': 0,
  113. 'audio.ins': 0,
  114. 'audio.outs': 0,
  115. 'midi.ins': 0,
  116. 'midi.outs': 0,
  117. 'parameters.ins': 0,
  118. 'parameters.outs': 0
  119. }
  120. global gDiscoveryProcess
  121. gDiscoveryProcess = None
  122. def findWinePrefix(filename, recursionLimit = 10):
  123. if recursionLimit == 0 or len(filename) < 5 or "/" not in filename:
  124. return ""
  125. path = filename[:filename.rfind("/")]
  126. if os.path.isdir(path + "/dosdevices"):
  127. return path
  128. return findWinePrefix(path, recursionLimit-1)
  129. def runCarlaDiscovery(itype, stype, filename, tool, wineSettings=None):
  130. if not os.path.exists(tool):
  131. qWarning("runCarlaDiscovery() - tool '%s' does not exist" % tool)
  132. return
  133. command = []
  134. if LINUX or MACOS:
  135. command.append("env")
  136. command.append("LANG=C")
  137. command.append("LD_PRELOAD=")
  138. if wineSettings is not None:
  139. command.append("WINEDEBUG=-all")
  140. if wineSettings['autoPrefix']:
  141. winePrefix = findWinePrefix(filename)
  142. else:
  143. winePrefix = ""
  144. if not winePrefix:
  145. envWinePrefix = os.getenv("WINEPREFIX")
  146. if envWinePrefix:
  147. winePrefix = envWinePrefix
  148. elif wineSettings['fallbackPrefix']:
  149. winePrefix = os.path.expanduser(wineSettings['fallbackPrefix'])
  150. else:
  151. winePrefix = os.path.expanduser("~/.wine")
  152. wineCMD = wineSettings['executable'] if wineSettings['executable'] else "wine"
  153. if tool.endswith("64.exe") and os.path.exists(wineCMD + "64"):
  154. wineCMD += "64"
  155. command.append("WINEPREFIX=" + winePrefix)
  156. command.append(wineCMD)
  157. command.append(tool)
  158. command.append(stype)
  159. command.append(filename)
  160. global gDiscoveryProcess
  161. gDiscoveryProcess = Popen(command, stdout=PIPE)
  162. pinfo = None
  163. plugins = []
  164. fakeLabel = os.path.basename(filename).rsplit(".", 1)[0]
  165. while True:
  166. try:
  167. line = gDiscoveryProcess.stdout.readline().decode("utf-8", errors="ignore")
  168. except:
  169. print("ERROR: discovery readline failed")
  170. break
  171. # line is valid, strip it
  172. if line:
  173. line = line.strip()
  174. # line is invalid, try poll() again
  175. elif gDiscoveryProcess.poll() is None:
  176. continue
  177. # line is invalid and poll() failed, stop here
  178. else:
  179. break
  180. if line == "carla-discovery::init::-----------":
  181. pinfo = deepcopy(PyPluginInfo)
  182. pinfo['type'] = itype
  183. pinfo['filename'] = filename if filename != ":all" else ""
  184. elif line == "carla-discovery::end::------------":
  185. if pinfo is not None:
  186. plugins.append(pinfo)
  187. del pinfo
  188. pinfo = None
  189. elif line == "Segmentation fault":
  190. print("carla-discovery::crash::%s crashed during discovery" % filename)
  191. elif line.startswith("err:module:import_dll Library"):
  192. print(line)
  193. elif line.startswith("carla-discovery::info::"):
  194. print("%s - %s" % (line, filename))
  195. elif line.startswith("carla-discovery::warning::"):
  196. print("%s - %s" % (line, filename))
  197. elif line.startswith("carla-discovery::error::"):
  198. print("%s - %s" % (line, filename))
  199. elif line.startswith("carla-discovery::"):
  200. if pinfo == None:
  201. continue
  202. try:
  203. prop, value = line.replace("carla-discovery::", "").split("::", 1)
  204. except:
  205. continue
  206. if prop == "build":
  207. if value.isdigit(): pinfo['build'] = int(value)
  208. elif prop == "name":
  209. pinfo['name'] = value if value else fakeLabel
  210. elif prop == "label":
  211. pinfo['label'] = value if value else fakeLabel
  212. elif prop == "maker":
  213. pinfo['maker'] = value
  214. elif prop == "uniqueId":
  215. if value.isdigit(): pinfo['uniqueId'] = int(value)
  216. elif prop == "hints":
  217. if value.isdigit(): pinfo['hints'] = int(value)
  218. elif prop == "audio.ins":
  219. if value.isdigit(): pinfo['audio.ins'] = int(value)
  220. elif prop == "audio.outs":
  221. if value.isdigit(): pinfo['audio.outs'] = int(value)
  222. elif prop == "midi.ins":
  223. if value.isdigit(): pinfo['midi.ins'] = int(value)
  224. elif prop == "midi.outs":
  225. if value.isdigit(): pinfo['midi.outs'] = int(value)
  226. elif prop == "parameters.ins":
  227. if value.isdigit(): pinfo['parameters.ins'] = int(value)
  228. elif prop == "parameters.outs":
  229. if value.isdigit(): pinfo['parameters.outs'] = int(value)
  230. elif prop == "uri":
  231. if value:
  232. pinfo['label'] = value
  233. else:
  234. # cannot use empty URIs
  235. del pinfo
  236. pinfo = None
  237. continue
  238. else:
  239. print("%s - %s (unknown property)" % (line, filename))
  240. # FIXME?
  241. tmp = gDiscoveryProcess
  242. gDiscoveryProcess = None
  243. del gDiscoveryProcess, tmp
  244. return plugins
  245. def killDiscovery():
  246. global gDiscoveryProcess
  247. if gDiscoveryProcess is not None:
  248. gDiscoveryProcess.kill()
  249. def checkPluginCached(desc, ptype):
  250. pinfo = deepcopy(PyPluginInfo)
  251. pinfo['build'] = BINARY_NATIVE
  252. pinfo['type'] = ptype
  253. pinfo['hints'] = desc['hints']
  254. pinfo['name'] = desc['name']
  255. pinfo['label'] = desc['label']
  256. pinfo['maker'] = desc['maker']
  257. pinfo['audio.ins'] = desc['audioIns']
  258. pinfo['audio.outs'] = desc['audioOuts']
  259. pinfo['midi.ins'] = desc['midiIns']
  260. pinfo['midi.outs'] = desc['midiOuts']
  261. pinfo['parameters.ins'] = desc['parameterIns']
  262. pinfo['parameters.outs'] = desc['parameterOuts']
  263. if ptype == PLUGIN_SFZ:
  264. pinfo['filename'] = pinfo['label']
  265. pinfo['label'] = pinfo['name']
  266. return pinfo
  267. def checkPluginLADSPA(filename, tool, wineSettings=None):
  268. return runCarlaDiscovery(PLUGIN_LADSPA, "LADSPA", filename, tool, wineSettings)
  269. def checkPluginDSSI(filename, tool, wineSettings=None):
  270. return runCarlaDiscovery(PLUGIN_DSSI, "DSSI", filename, tool, wineSettings)
  271. def checkPluginLV2(filename, tool, wineSettings=None):
  272. return runCarlaDiscovery(PLUGIN_LV2, "LV2", filename, tool, wineSettings)
  273. def checkPluginVST2(filename, tool, wineSettings=None):
  274. return runCarlaDiscovery(PLUGIN_VST2, "VST2", filename, tool, wineSettings)
  275. def checkFileSF2(filename, tool):
  276. return runCarlaDiscovery(PLUGIN_SF2, "SF2", filename, tool)
  277. def checkFileSFZ(filename, tool):
  278. return runCarlaDiscovery(PLUGIN_SFZ, "SFZ", filename, tool)
  279. # ----------------------------------------------------------------------------------------------------------------------
  280. # Separate Thread for Plugin Search
  281. class SearchPluginsThread(QThread):
  282. pluginLook = pyqtSignal(int, str)
  283. def __init__(self, parent, pathBinaries):
  284. QThread.__init__(self, parent)
  285. self.fContinueChecking = False
  286. self.fPathBinaries = pathBinaries
  287. self.fCheckNative = False
  288. self.fCheckPosix32 = False
  289. self.fCheckPosix64 = False
  290. self.fCheckWin32 = False
  291. self.fCheckWin64 = False
  292. self.fCheckLADSPA = False
  293. self.fCheckDSSI = False
  294. self.fCheckLV2 = False
  295. self.fCheckVST2 = False
  296. self.fCheckSF2 = False
  297. self.fCheckSFZ = False
  298. if WINDOWS:
  299. toolNative = "carla-discovery-win64.exe" if kIs64bit else "carla-discovery-win32.exe"
  300. self.fWineSettings = None
  301. else:
  302. toolNative = "carla-discovery-native"
  303. settings = QSettings("falkTX", "Carla2")
  304. self.fWineSettings = {
  305. 'executable' : settings.value(CARLA_KEY_WINE_EXECUTABLE, CARLA_DEFAULT_WINE_EXECUTABLE, type=str),
  306. 'autoPrefix' : settings.value(CARLA_KEY_WINE_AUTO_PREFIX, CARLA_DEFAULT_WINE_AUTO_PREFIX, type=bool),
  307. 'fallbackPrefix': settings.value(CARLA_KEY_WINE_FALLBACK_PREFIX, CARLA_DEFAULT_WINE_FALLBACK_PREFIX, type=str)
  308. }
  309. del settings
  310. self.fToolNative = os.path.join(pathBinaries, toolNative)
  311. if not os.path.exists(self.fToolNative):
  312. self.fToolNative = ""
  313. self.fCurCount = 0
  314. self.fCurPercentValue = 0
  315. self.fLastCheckValue = 0
  316. self.fSomethingChanged = False
  317. # -------------------------------------------------------------
  318. def hasSomethingChanged(self):
  319. return self.fSomethingChanged
  320. def setSearchBinaryTypes(self, native, posix32, posix64, win32, win64):
  321. self.fCheckNative = native
  322. self.fCheckPosix32 = posix32
  323. self.fCheckPosix64 = posix64
  324. self.fCheckWin32 = win32
  325. self.fCheckWin64 = win64
  326. def setSearchPluginTypes(self, ladspa, dssi, lv2, vst2, sf2, sfz):
  327. self.fCheckLADSPA = ladspa
  328. self.fCheckDSSI = dssi
  329. self.fCheckLV2 = lv2
  330. self.fCheckVST2 = vst2
  331. self.fCheckSF2 = sf2
  332. self.fCheckSFZ = sfz
  333. def stop(self):
  334. self.fContinueChecking = False
  335. def run(self):
  336. settingsDB = QSettings("falkTX", "CarlaPlugins4")
  337. self.fContinueChecking = True
  338. self.fCurCount = 0
  339. # looking for plugins via external discovery
  340. pluginCount = 0
  341. if self.fCheckLADSPA: pluginCount += 1
  342. if self.fCheckDSSI: pluginCount += 1
  343. if self.fCheckVST2: pluginCount += 1
  344. # Increase count by the number of externally discoverable plugin types
  345. if self.fCheckNative:
  346. self.fCurCount += pluginCount
  347. if self.fCheckPosix32:
  348. self.fCurCount += pluginCount
  349. if self.fCheckPosix64:
  350. self.fCurCount += pluginCount
  351. if self.fCheckWin32:
  352. self.fCurCount += pluginCount
  353. if self.fCheckWin64:
  354. self.fCurCount += pluginCount
  355. # Special case for cached plugins, only "search" for native plugins (does not need tool)
  356. if self.fCheckLV2:
  357. if self.fCheckNative:
  358. self.fCurCount += 1
  359. else:
  360. self.fCheckLV2 = False
  361. if self.fCheckSFZ:
  362. if self.fCheckNative:
  363. self.fCurCount += 1
  364. else:
  365. self.fCheckSFZ = False
  366. # Special case for Sound Kits, only search native
  367. if self.fCheckNative and self.fToolNative:
  368. if self.fCheckSF2: self.fCurCount += 1
  369. else:
  370. self.fCheckSF2 = False
  371. if self.fCurCount == 0:
  372. return
  373. self.fCurPercentValue = 100.0 / self.fCurCount
  374. self.fLastCheckValue = 0.0
  375. del pluginCount
  376. if HAIKU:
  377. OS = "HAIKU"
  378. elif LINUX:
  379. OS = "LINUX"
  380. elif MACOS:
  381. OS = "MACOS"
  382. elif WINDOWS:
  383. OS = "WINDOWS"
  384. else:
  385. OS = "UNKNOWN"
  386. if not self.fContinueChecking: return
  387. self.fSomethingChanged = True
  388. if self.fCheckLADSPA:
  389. checkValue = 0.0
  390. if haveLRDF:
  391. if self.fCheckNative: checkValue += 0.1
  392. if self.fCheckPosix32: checkValue += 0.1
  393. if self.fCheckPosix64: checkValue += 0.1
  394. if self.fCheckWin32: checkValue += 0.1
  395. if self.fCheckWin64: checkValue += 0.1
  396. rdfPadValue = self.fCurPercentValue * checkValue
  397. if self.fCheckNative:
  398. plugins = self._checkLADSPA(OS, self.fToolNative)
  399. settingsDB.setValue("Plugins/LADSPA_native", plugins)
  400. if not self.fContinueChecking: return
  401. if self.fCheckPosix32:
  402. plugins = self._checkLADSPA(OS, os.path.join(self.fPathBinaries, "carla-discovery-posix32"))
  403. settingsDB.setValue("Plugins/LADSPA_posix32", plugins)
  404. if not self.fContinueChecking: return
  405. if self.fCheckPosix64:
  406. plugins = self._checkLADSPA(OS, os.path.join(self.fPathBinaries, "carla-discovery-posix64"))
  407. settingsDB.setValue("Plugins/LADSPA_posix64", plugins)
  408. if not self.fContinueChecking: return
  409. if self.fCheckWin32:
  410. plugins = self._checkLADSPA("WINDOWS", os.path.join(self.fPathBinaries, "carla-discovery-win32.exe"), not WINDOWS)
  411. settingsDB.setValue("Plugins/LADSPA_win32", plugins)
  412. if not self.fContinueChecking: return
  413. if self.fCheckWin64:
  414. plugins = self._checkLADSPA("WINDOWS", os.path.join(self.fPathBinaries, "carla-discovery-win64.exe"), not WINDOWS)
  415. settingsDB.setValue("Plugins/LADSPA_win64", plugins)
  416. settingsDB.sync()
  417. if not self.fContinueChecking: return
  418. if haveLRDF and checkValue > 0:
  419. startValue = self.fLastCheckValue - rdfPadValue
  420. self._pluginLook(startValue, "LADSPA RDFs...")
  421. try:
  422. ladspaRdfInfo = ladspa_rdf.recheck_all_plugins(self, startValue, self.fCurPercentValue, checkValue)
  423. except:
  424. ladspaRdfInfo = None
  425. if ladspaRdfInfo is not None:
  426. settingsDir = os.path.join(HOME, ".config", "falkTX")
  427. fdLadspa = open(os.path.join(settingsDir, "ladspa_rdf.db"), 'w')
  428. json.dump(ladspaRdfInfo, fdLadspa)
  429. fdLadspa.close()
  430. if not self.fContinueChecking: return
  431. if self.fCheckDSSI:
  432. if self.fCheckNative:
  433. plugins = self._checkDSSI(OS, self.fToolNative)
  434. settingsDB.setValue("Plugins/DSSI_native", plugins)
  435. if not self.fContinueChecking: return
  436. if self.fCheckPosix32:
  437. plugins = self._checkDSSI(OS, os.path.join(self.fPathBinaries, "carla-discovery-posix32"))
  438. settingsDB.setValue("Plugins/DSSI_posix32", plugins)
  439. if not self.fContinueChecking: return
  440. if self.fCheckPosix64:
  441. plugins = self._checkDSSI(OS, os.path.join(self.fPathBinaries, "carla-discovery-posix64"))
  442. settingsDB.setValue("Plugins/DSSI_posix64", plugins)
  443. if not self.fContinueChecking: return
  444. if self.fCheckWin32:
  445. plugins = self._checkDSSI("WINDOWS", os.path.join(self.fPathBinaries, "carla-discovery-win32.exe"), not WINDOWS)
  446. settingsDB.setValue("Plugins/DSSI_win32", plugins)
  447. if not self.fContinueChecking: return
  448. if self.fCheckWin64:
  449. plugins = self._checkDSSI("WINDOWS", os.path.join(self.fPathBinaries, "carla-discovery-win64.exe"), not WINDOWS)
  450. settingsDB.setValue("Plugins/DSSI_win64", plugins)
  451. settingsDB.sync()
  452. if not self.fContinueChecking: return
  453. if self.fCheckLV2:
  454. plugins = self._checkLv2Cached()
  455. settingsDB.setValue("Plugins/LV2", plugins)
  456. settingsDB.sync()
  457. if not self.fContinueChecking: return
  458. if self.fCheckVST2:
  459. if self.fCheckNative:
  460. plugins = self._checkVST2(OS, self.fToolNative)
  461. settingsDB.setValue("Plugins/VST2_native", plugins)
  462. if not self.fContinueChecking: return
  463. if self.fCheckPosix32:
  464. plugins = self._checkVST2(OS, os.path.join(self.fPathBinaries, "carla-discovery-posix32"))
  465. settingsDB.setValue("Plugins/VST2_posix32", plugins)
  466. if not self.fContinueChecking: return
  467. if self.fCheckPosix64:
  468. plugins = self._checkVST2(OS, os.path.join(self.fPathBinaries, "carla-discovery-posix64"))
  469. settingsDB.setValue("Plugins/VST2_posix64", plugins)
  470. if not self.fContinueChecking: return
  471. if self.fCheckWin32:
  472. plugins = self._checkVST2("WINDOWS", os.path.join(self.fPathBinaries, "carla-discovery-win32.exe"), not WINDOWS)
  473. settingsDB.setValue("Plugins/VST2_win32", plugins)
  474. if not self.fContinueChecking: return
  475. if self.fCheckWin64:
  476. plugins = self._checkVST2("WINDOWS", os.path.join(self.fPathBinaries, "carla-discovery-win64.exe"), not WINDOWS)
  477. settingsDB.setValue("Plugins/VST2_win64", plugins)
  478. if not self.fContinueChecking: return
  479. settingsDB.sync()
  480. if not self.fContinueChecking: return
  481. if self.fCheckSF2:
  482. settings = QSettings("falkTX", "Carla2")
  483. SF2_PATH = toList(settings.value(CARLA_KEY_PATHS_SF2, CARLA_DEFAULT_SF2_PATH))
  484. del settings
  485. kits = self._checkKIT(SF2_PATH, "sf2")
  486. settingsDB.setValue("Plugins/SF2", kits)
  487. settingsDB.sync()
  488. if not self.fContinueChecking: return
  489. if self.fCheckSFZ:
  490. kits = self._checkSfzCached()
  491. settingsDB.setValue("Plugins/SFZ", kits)
  492. settingsDB.sync()
  493. def _checkLADSPA(self, OS, tool, isWine=False):
  494. ladspaBinaries = []
  495. ladspaPlugins = []
  496. self._pluginLook(self.fLastCheckValue, "LADSPA plugins...")
  497. settings = QSettings("falkTX", "Carla2")
  498. LADSPA_PATH = toList(settings.value(CARLA_KEY_PATHS_LADSPA, CARLA_DEFAULT_LADSPA_PATH))
  499. del settings
  500. for iPATH in LADSPA_PATH:
  501. binaries = findBinaries(iPATH, OS)
  502. for binary in binaries:
  503. if binary not in ladspaBinaries:
  504. ladspaBinaries.append(binary)
  505. ladspaBinaries.sort()
  506. if not self.fContinueChecking:
  507. return ladspaPlugins
  508. for i in range(len(ladspaBinaries)):
  509. ladspa = ladspaBinaries[i]
  510. percent = ( float(i) / len(ladspaBinaries) ) * self.fCurPercentValue
  511. self._pluginLook((self.fLastCheckValue + percent) * 0.9, ladspa)
  512. plugins = checkPluginLADSPA(ladspa, tool, self.fWineSettings if isWine else None)
  513. if plugins:
  514. ladspaPlugins.append(plugins)
  515. if not self.fContinueChecking:
  516. break
  517. self.fLastCheckValue += self.fCurPercentValue
  518. return ladspaPlugins
  519. def _checkDSSI(self, OS, tool, isWine=False):
  520. dssiBinaries = []
  521. dssiPlugins = []
  522. self._pluginLook(self.fLastCheckValue, "DSSI plugins...")
  523. settings = QSettings("falkTX", "Carla2")
  524. DSSI_PATH = toList(settings.value(CARLA_KEY_PATHS_DSSI, CARLA_DEFAULT_DSSI_PATH))
  525. del settings
  526. for iPATH in DSSI_PATH:
  527. binaries = findBinaries(iPATH, OS)
  528. for binary in binaries:
  529. if binary not in dssiBinaries:
  530. dssiBinaries.append(binary)
  531. dssiBinaries.sort()
  532. if not self.fContinueChecking:
  533. return dssiPlugins
  534. for i in range(len(dssiBinaries)):
  535. dssi = dssiBinaries[i]
  536. percent = ( float(i) / len(dssiBinaries) ) * self.fCurPercentValue
  537. self._pluginLook(self.fLastCheckValue + percent, dssi)
  538. plugins = checkPluginDSSI(dssi, tool, self.fWineSettings if isWine else None)
  539. if plugins:
  540. dssiPlugins.append(plugins)
  541. if not self.fContinueChecking:
  542. break
  543. self.fLastCheckValue += self.fCurPercentValue
  544. return dssiPlugins
  545. def _checkVST2(self, OS, tool, isWine=False):
  546. vst2Binaries = []
  547. vstPlugins = []
  548. if MACOS and not isWine:
  549. self._pluginLook(self.fLastCheckValue, "VST2 bundles...")
  550. else:
  551. self._pluginLook(self.fLastCheckValue, "VST2 plugins...")
  552. settings = QSettings("falkTX", "Carla2")
  553. VST2_PATH = toList(settings.value(CARLA_KEY_PATHS_VST2, CARLA_DEFAULT_VST2_PATH))
  554. del settings
  555. for iPATH in VST2_PATH:
  556. if MACOS and not isWine:
  557. binaries = findMacVSTBundles(iPATH)
  558. else:
  559. binaries = findBinaries(iPATH, OS)
  560. for binary in binaries:
  561. if binary not in vst2Binaries:
  562. vst2Binaries.append(binary)
  563. vst2Binaries.sort()
  564. if not self.fContinueChecking:
  565. return vstPlugins
  566. for i in range(len(vst2Binaries)):
  567. vst2 = vst2Binaries[i]
  568. percent = ( float(i) / len(vst2Binaries) ) * self.fCurPercentValue
  569. self._pluginLook(self.fLastCheckValue + percent, vst2)
  570. plugins = checkPluginVST2(vst2, tool, self.fWineSettings if isWine else None)
  571. if plugins:
  572. vstPlugins.append(plugins)
  573. if not self.fContinueChecking:
  574. break
  575. self.fLastCheckValue += self.fCurPercentValue
  576. return vstPlugins
  577. def _checkKIT(self, kitPATH, kitExtension):
  578. kitFiles = []
  579. kitPlugins = []
  580. for iPATH in kitPATH:
  581. files = findFilenames(iPATH, kitExtension)
  582. for file_ in files:
  583. if file_ not in kitFiles:
  584. kitFiles.append(file_)
  585. kitFiles.sort()
  586. if not self.fContinueChecking:
  587. return kitPlugins
  588. for i in range(len(kitFiles)):
  589. kit = kitFiles[i]
  590. percent = ( float(i) / len(kitFiles) ) * self.fCurPercentValue
  591. self._pluginLook(self.fLastCheckValue + percent, kit)
  592. if kitExtension == "sf2":
  593. plugins = checkFileSF2(kit, self.fToolNative)
  594. else:
  595. plugins = None
  596. if plugins:
  597. kitPlugins.append(plugins)
  598. if not self.fContinueChecking:
  599. break
  600. self.fLastCheckValue += self.fCurPercentValue
  601. return kitPlugins
  602. def _checkLv2Cached(self):
  603. settings = QSettings("falkTX", "Carla2")
  604. PLUG_PATH = splitter.join(toList(settings.value(CARLA_KEY_PATHS_LV2, CARLA_DEFAULT_LV2_PATH)))
  605. del settings
  606. lv2Plugins = []
  607. self._pluginLook(self.fLastCheckValue, "LV2 plugins...")
  608. count = gCarla.utils.get_cached_plugin_count(PLUGIN_LV2, PLUG_PATH)
  609. if not self.fContinueChecking:
  610. return lv2Plugins
  611. for i in range(count):
  612. descInfo = gCarla.utils.get_cached_plugin_info(PLUGIN_LV2, i)
  613. percent = ( float(i) / count ) * self.fCurPercentValue
  614. self._pluginLook(self.fLastCheckValue + percent, descInfo['label'])
  615. if not descInfo['valid']:
  616. continue
  617. lv2Plugins.append(checkPluginCached(descInfo, PLUGIN_LV2))
  618. if not self.fContinueChecking:
  619. break
  620. self.fLastCheckValue += self.fCurPercentValue
  621. return lv2Plugins
  622. def _checkSfzCached(self):
  623. settings = QSettings("falkTX", "Carla2")
  624. PLUG_PATH = splitter.join(toList(settings.value(CARLA_KEY_PATHS_SFZ, CARLA_DEFAULT_SFZ_PATH)))
  625. del settings
  626. sfzKits = []
  627. self._pluginLook(self.fLastCheckValue, "SFZ kits...")
  628. count = gCarla.utils.get_cached_plugin_count(PLUGIN_SFZ, PLUG_PATH)
  629. if not self.fContinueChecking:
  630. return sfzKits
  631. for i in range(count):
  632. descInfo = gCarla.utils.get_cached_plugin_info(PLUGIN_SFZ, i)
  633. percent = ( float(i) / count ) * self.fCurPercentValue
  634. self._pluginLook(self.fLastCheckValue + percent, descInfo['label'])
  635. if not descInfo['valid']:
  636. continue
  637. sfzKits.append(checkPluginCached(descInfo, PLUGIN_SFZ))
  638. if not self.fContinueChecking:
  639. break
  640. self.fLastCheckValue += self.fCurPercentValue
  641. return sfzKits
  642. def _pluginLook(self, percent, plugin):
  643. self.pluginLook.emit(percent, plugin)
  644. # ---------------------------------------------------------------------------------------------------------------------
  645. # Plugin Refresh Dialog
  646. class PluginRefreshW(QDialog):
  647. def __init__(self, parent, host):
  648. QDialog.__init__(self, parent)
  649. self.host = host
  650. self.ui = ui_carla_refresh.Ui_PluginRefreshW()
  651. self.ui.setupUi(self)
  652. if False:
  653. # kdevelop likes this :)
  654. self.host = host = CarlaHostNull()
  655. # -------------------------------------------------------------------------------------------------------------
  656. # Internal stuff
  657. hasNative = os.path.exists(os.path.join(self.host.pathBinaries, "carla-discovery-native"))
  658. hasPosix32 = os.path.exists(os.path.join(self.host.pathBinaries, "carla-discovery-posix32"))
  659. hasPosix64 = os.path.exists(os.path.join(self.host.pathBinaries, "carla-discovery-posix64"))
  660. hasWin32 = os.path.exists(os.path.join(self.host.pathBinaries, "carla-discovery-win32.exe"))
  661. hasWin64 = os.path.exists(os.path.join(self.host.pathBinaries, "carla-discovery-win64.exe"))
  662. self.fThread = SearchPluginsThread(self, host.pathBinaries)
  663. self.fIconYes = getIcon("dialog-ok-apply").pixmap(16, 16)
  664. self.fIconNo = getIcon("dialog-error").pixmap(16, 16)
  665. # -------------------------------------------------------------------------------------------------------------
  666. # Set-up GUI
  667. self.ui.b_skip.setVisible(False)
  668. if HAIKU:
  669. self.ui.ch_posix32.setText("Haiku 32bit")
  670. self.ui.ch_posix64.setText("Haiku 64bit")
  671. elif LINUX:
  672. self.ui.ch_posix32.setText("Linux 32bit")
  673. self.ui.ch_posix64.setText("Linux 64bit")
  674. elif MACOS:
  675. self.ui.ch_posix32.setText("MacOS 32bit")
  676. self.ui.ch_posix64.setText("MacOS 64bit")
  677. if hasPosix32 and not WINDOWS:
  678. self.ui.ico_posix32.setPixmap(self.fIconYes)
  679. else:
  680. self.ui.ico_posix32.setPixmap(self.fIconNo)
  681. self.ui.ch_posix32.setEnabled(False)
  682. if hasPosix64 and not WINDOWS:
  683. self.ui.ico_posix64.setPixmap(self.fIconYes)
  684. else:
  685. self.ui.ico_posix64.setPixmap(self.fIconNo)
  686. self.ui.ch_posix64.setEnabled(False)
  687. if hasWin32:
  688. self.ui.ico_win32.setPixmap(self.fIconYes)
  689. else:
  690. self.ui.ico_win32.setPixmap(self.fIconNo)
  691. self.ui.ch_win32.setEnabled(False)
  692. if hasWin64:
  693. self.ui.ico_win64.setPixmap(self.fIconYes)
  694. else:
  695. self.ui.ico_win64.setPixmap(self.fIconNo)
  696. self.ui.ch_win64.setEnabled(False)
  697. if haveLRDF:
  698. self.ui.ico_rdflib.setPixmap(self.fIconYes)
  699. else:
  700. self.ui.ico_rdflib.setPixmap(self.fIconNo)
  701. if WINDOWS:
  702. if kIs64bit:
  703. hasNative = hasWin64
  704. hasNonNative = hasWin32
  705. self.ui.ch_win64.setEnabled(False)
  706. self.ui.ch_win64.setVisible(False)
  707. self.ui.ico_win64.setVisible(False)
  708. self.ui.label_win64.setVisible(False)
  709. else:
  710. hasNative = hasWin32
  711. hasNonNative = hasWin64
  712. self.ui.ch_win32.setEnabled(False)
  713. self.ui.ch_win32.setVisible(False)
  714. self.ui.ico_win32.setVisible(False)
  715. self.ui.label_win32.setVisible(False)
  716. self.ui.ch_posix32.setEnabled(False)
  717. self.ui.ch_posix32.setVisible(False)
  718. self.ui.ch_posix64.setEnabled(False)
  719. self.ui.ch_posix64.setVisible(False)
  720. self.ui.ico_posix32.hide()
  721. self.ui.ico_posix64.hide()
  722. self.ui.label_posix32.hide()
  723. self.ui.label_posix64.hide()
  724. self.ui.ico_rdflib.hide()
  725. self.ui.label_rdflib.hide()
  726. else:
  727. if kIs64bit:
  728. hasNonNative = bool(hasPosix32 or hasWin32 or hasWin64)
  729. self.ui.ch_posix64.setEnabled(False)
  730. self.ui.ch_posix64.setVisible(False)
  731. self.ui.ico_posix64.setVisible(False)
  732. self.ui.label_posix64.setVisible(False)
  733. else:
  734. hasNonNative = bool(hasPosix64 or hasWin32 or hasWin64)
  735. self.ui.ch_posix32.setEnabled(False)
  736. self.ui.ch_posix32.setVisible(False)
  737. self.ui.ico_posix32.setVisible(False)
  738. self.ui.label_posix32.setVisible(False)
  739. if hasNative:
  740. self.ui.ico_native.setPixmap(self.fIconYes)
  741. else:
  742. self.ui.ico_native.setPixmap(self.fIconNo)
  743. self.ui.ch_native.setEnabled(False)
  744. self.ui.ch_sf2.setEnabled(False)
  745. self.ui.ch_sfz.setEnabled(False)
  746. if not hasNonNative:
  747. self.ui.ch_ladspa.setEnabled(False)
  748. self.ui.ch_dssi.setEnabled(False)
  749. self.ui.ch_vst.setEnabled(False)
  750. self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
  751. # -------------------------------------------------------------------------------------------------------------
  752. # Load settings
  753. self.loadSettings()
  754. # -------------------------------------------------------------------------------------------------------------
  755. # Hide bridges if disabled
  756. # NOTE: We Assume win32 carla build will not run win64 plugins
  757. if (WINDOWS and not kIs64bit) or not host.showPluginBridges:
  758. self.ui.ch_native.setChecked(True)
  759. self.ui.ch_native.setEnabled(False)
  760. self.ui.ch_native.setVisible(False)
  761. self.ui.ch_posix32.setChecked(False)
  762. self.ui.ch_posix32.setEnabled(False)
  763. self.ui.ch_posix32.setVisible(False)
  764. self.ui.ch_posix64.setChecked(False)
  765. self.ui.ch_posix64.setEnabled(False)
  766. self.ui.ch_posix64.setVisible(False)
  767. self.ui.ch_win32.setChecked(False)
  768. self.ui.ch_win32.setEnabled(False)
  769. self.ui.ch_win32.setVisible(False)
  770. self.ui.ch_win64.setChecked(False)
  771. self.ui.ch_win64.setEnabled(False)
  772. self.ui.ch_win64.setVisible(False)
  773. self.ui.ico_posix32.hide()
  774. self.ui.ico_posix64.hide()
  775. self.ui.ico_win32.hide()
  776. self.ui.ico_win64.hide()
  777. self.ui.label_posix32.hide()
  778. self.ui.label_posix64.hide()
  779. self.ui.label_win32.hide()
  780. self.ui.label_win64.hide()
  781. self.ui.sep_format.hide()
  782. elif not (WINDOWS or host.showWineBridges):
  783. self.ui.ch_win32.setChecked(False)
  784. self.ui.ch_win32.setEnabled(False)
  785. self.ui.ch_win32.setVisible(False)
  786. self.ui.ch_win64.setChecked(False)
  787. self.ui.ch_win64.setEnabled(False)
  788. self.ui.ch_win64.setVisible(False)
  789. self.ui.ico_win32.hide()
  790. self.ui.ico_win64.hide()
  791. self.ui.label_win32.hide()
  792. self.ui.label_win64.hide()
  793. # Disable non-supported features
  794. features = gCarla.utils.get_supported_features()
  795. if "sf2" not in features:
  796. self.ui.ch_sf2.setChecked(False)
  797. self.ui.ch_sf2.setEnabled(False)
  798. # -------------------------------------------------------------------------------------------------------------
  799. # Resize to minimum size, as it's very likely UI stuff was hidden
  800. self.resize(self.minimumSize())
  801. # -------------------------------------------------------------------------------------------------------------
  802. # Set-up connections
  803. self.finished.connect(self.slot_saveSettings)
  804. self.ui.b_start.clicked.connect(self.slot_start)
  805. self.ui.b_skip.clicked.connect(self.slot_skip)
  806. self.ui.ch_native.clicked.connect(self.slot_checkTools)
  807. self.ui.ch_posix32.clicked.connect(self.slot_checkTools)
  808. self.ui.ch_posix64.clicked.connect(self.slot_checkTools)
  809. self.ui.ch_win32.clicked.connect(self.slot_checkTools)
  810. self.ui.ch_win64.clicked.connect(self.slot_checkTools)
  811. self.ui.ch_ladspa.clicked.connect(self.slot_checkTools)
  812. self.ui.ch_dssi.clicked.connect(self.slot_checkTools)
  813. self.ui.ch_lv2.clicked.connect(self.slot_checkTools)
  814. self.ui.ch_vst.clicked.connect(self.slot_checkTools)
  815. self.ui.ch_sf2.clicked.connect(self.slot_checkTools)
  816. self.ui.ch_sfz.clicked.connect(self.slot_checkTools)
  817. self.fThread.pluginLook.connect(self.slot_handlePluginLook)
  818. self.fThread.finished.connect(self.slot_handlePluginThreadFinished)
  819. # -------------------------------------------------------------------------------------------------------------
  820. # Post-connect setup
  821. self.slot_checkTools()
  822. # -----------------------------------------------------------------------------------------------------------------
  823. def loadSettings(self):
  824. settings = QSettings("falkTX", "CarlaRefresh2")
  825. check = settings.value("PluginDatabase/SearchLADSPA", True, type=bool) and self.ui.ch_ladspa.isEnabled()
  826. self.ui.ch_ladspa.setChecked(check)
  827. check = settings.value("PluginDatabase/SearchDSSI", True, type=bool) and self.ui.ch_dssi.isEnabled()
  828. self.ui.ch_dssi.setChecked(check)
  829. check = settings.value("PluginDatabase/SearchLV2", True, type=bool) and self.ui.ch_lv2.isEnabled()
  830. self.ui.ch_lv2.setChecked(check)
  831. check = settings.value("PluginDatabase/SearchVST2", True, type=bool) and self.ui.ch_vst.isEnabled()
  832. self.ui.ch_vst.setChecked(check)
  833. check = settings.value("PluginDatabase/SearchSF2", False, type=bool) and self.ui.ch_sf2.isEnabled()
  834. self.ui.ch_sf2.setChecked(check)
  835. check = settings.value("PluginDatabase/SearchSFZ", False, type=bool) and self.ui.ch_sfz.isEnabled()
  836. self.ui.ch_sfz.setChecked(check)
  837. check = settings.value("PluginDatabase/SearchNative", True, type=bool) and self.ui.ch_native.isEnabled()
  838. self.ui.ch_native.setChecked(check)
  839. check = settings.value("PluginDatabase/SearchPOSIX32", False, type=bool) and self.ui.ch_posix32.isEnabled()
  840. self.ui.ch_posix32.setChecked(check)
  841. check = settings.value("PluginDatabase/SearchPOSIX64", False, type=bool) and self.ui.ch_posix64.isEnabled()
  842. self.ui.ch_posix64.setChecked(check)
  843. check = settings.value("PluginDatabase/SearchWin32", False, type=bool) and self.ui.ch_win32.isEnabled()
  844. self.ui.ch_win32.setChecked(check)
  845. check = settings.value("PluginDatabase/SearchWin64", False, type=bool) and self.ui.ch_win64.isEnabled()
  846. self.ui.ch_win64.setChecked(check)
  847. self.ui.ch_do_checks.setChecked(settings.value("PluginDatabase/DoChecks", False, type=bool))
  848. # ------------------------------------------------------------------------------------------------------------------
  849. @pyqtSlot()
  850. def slot_saveSettings(self):
  851. settings = QSettings("falkTX", "CarlaRefresh2")
  852. settings.setValue("PluginDatabase/SearchLADSPA", self.ui.ch_ladspa.isChecked())
  853. settings.setValue("PluginDatabase/SearchDSSI", self.ui.ch_dssi.isChecked())
  854. settings.setValue("PluginDatabase/SearchLV2", self.ui.ch_lv2.isChecked())
  855. settings.setValue("PluginDatabase/SearchVST2", self.ui.ch_vst.isChecked())
  856. settings.setValue("PluginDatabase/SearchSF2", self.ui.ch_sf2.isChecked())
  857. settings.setValue("PluginDatabase/SearchSFZ", self.ui.ch_sfz.isChecked())
  858. settings.setValue("PluginDatabase/SearchNative", self.ui.ch_native.isChecked())
  859. settings.setValue("PluginDatabase/SearchPOSIX32", self.ui.ch_posix32.isChecked())
  860. settings.setValue("PluginDatabase/SearchPOSIX64", self.ui.ch_posix64.isChecked())
  861. settings.setValue("PluginDatabase/SearchWin32", self.ui.ch_win32.isChecked())
  862. settings.setValue("PluginDatabase/SearchWin64", self.ui.ch_win64.isChecked())
  863. settings.setValue("PluginDatabase/DoChecks", self.ui.ch_do_checks.isChecked())
  864. # ------------------------------------------------------------------------------------------------------------------
  865. @pyqtSlot()
  866. def slot_start(self):
  867. self.ui.progressBar.setMinimum(0)
  868. self.ui.progressBar.setMaximum(100)
  869. self.ui.progressBar.setValue(0)
  870. self.ui.b_start.setEnabled(False)
  871. self.ui.b_skip.setVisible(True)
  872. self.ui.b_close.setVisible(False)
  873. self.ui.group_types.setEnabled(False)
  874. self.ui.group_options.setEnabled(False)
  875. if self.ui.ch_do_checks.isChecked():
  876. gCarla.utils.unsetenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS")
  877. else:
  878. gCarla.utils.setenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS", "true")
  879. native, posix32, posix64, win32, win64 = (self.ui.ch_native.isChecked(),
  880. self.ui.ch_posix32.isChecked(), self.ui.ch_posix64.isChecked(),
  881. self.ui.ch_win32.isChecked(), self.ui.ch_win64.isChecked())
  882. ladspa, dssi, lv2, vst, sf2, sfz = (self.ui.ch_ladspa.isChecked(), self.ui.ch_dssi.isChecked(),
  883. self.ui.ch_lv2.isChecked(), self.ui.ch_vst.isChecked(),
  884. self.ui.ch_sf2.isChecked(), self.ui.ch_sfz.isChecked())
  885. self.fThread.setSearchBinaryTypes(native, posix32, posix64, win32, win64)
  886. self.fThread.setSearchPluginTypes(ladspa, dssi, lv2, vst, sf2, sfz)
  887. self.fThread.start()
  888. # ------------------------------------------------------------------------------------------------------------------
  889. @pyqtSlot()
  890. def slot_skip(self):
  891. killDiscovery()
  892. # ------------------------------------------------------------------------------------------------------------------
  893. @pyqtSlot()
  894. def slot_checkTools(self):
  895. enabled1 = bool(self.ui.ch_native.isChecked() or
  896. self.ui.ch_posix32.isChecked() or self.ui.ch_posix64.isChecked() or
  897. self.ui.ch_win32.isChecked() or self.ui.ch_win64.isChecked())
  898. enabled2 = bool(self.ui.ch_ladspa.isChecked() or self.ui.ch_dssi.isChecked() or
  899. self.ui.ch_lv2.isChecked() or self.ui.ch_vst.isChecked() or
  900. self.ui.ch_sf2.isChecked() or self.ui.ch_sfz.isChecked())
  901. self.ui.b_start.setEnabled(enabled1 and enabled2)
  902. # ------------------------------------------------------------------------------------------------------------------
  903. @pyqtSlot(int, str)
  904. def slot_handlePluginLook(self, percent, plugin):
  905. self.ui.progressBar.setFormat("%s" % plugin)
  906. self.ui.progressBar.setValue(percent)
  907. # ------------------------------------------------------------------------------------------------------------------
  908. @pyqtSlot()
  909. def slot_handlePluginThreadFinished(self):
  910. self.ui.progressBar.setMinimum(0)
  911. self.ui.progressBar.setMaximum(1)
  912. self.ui.progressBar.setValue(1)
  913. self.ui.progressBar.setFormat(self.tr("Done"))
  914. self.ui.b_start.setEnabled(True)
  915. self.ui.b_skip.setVisible(False)
  916. self.ui.b_close.setVisible(True)
  917. self.ui.group_types.setEnabled(True)
  918. self.ui.group_options.setEnabled(True)
  919. # ------------------------------------------------------------------------------------------------------------------
  920. def closeEvent(self, event):
  921. if self.fThread.isRunning():
  922. self.fThread.stop()
  923. killDiscovery()
  924. #self.fThread.terminate()
  925. self.fThread.wait()
  926. if self.fThread.hasSomethingChanged():
  927. self.accept()
  928. else:
  929. self.reject()
  930. QDialog.closeEvent(self, event)
  931. # ------------------------------------------------------------------------------------------------------------------
  932. def done(self, r):
  933. QDialog.done(self, r)
  934. self.close()
  935. # ----------------------------------------------------------------------------------------------------------------------
  936. # Plugin Database Dialog
  937. class PluginDatabaseW(QDialog):
  938. def __init__(self, parent, host):
  939. QDialog.__init__(self, parent)
  940. self.host = host
  941. self.ui = ui_carla_database.Ui_PluginDatabaseW()
  942. self.ui.setupUi(self)
  943. if False:
  944. # kdevelop likes this :)
  945. host = CarlaHostNull()
  946. self.host = host
  947. # ----------------------------------------------------------------------------------------------------
  948. # Internal stuff
  949. self.fLastTableIndex = 0
  950. self.fRetPlugin = None
  951. self.fRealParent = parent
  952. # ----------------------------------------------------------------------------------------------------
  953. # Set-up GUI
  954. self.ui.b_add.setEnabled(False)
  955. if BINARY_NATIVE in (BINARY_POSIX32, BINARY_WIN32):
  956. self.ui.ch_bridged.setText(self.tr("Bridged (64bit)"))
  957. else:
  958. self.ui.ch_bridged.setText(self.tr("Bridged (32bit)"))
  959. if not (LINUX or MACOS):
  960. self.ui.ch_bridged_wine.setChecked(False)
  961. self.ui.ch_bridged_wine.setEnabled(False)
  962. self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
  963. # ----------------------------------------------------------------------------------------------------
  964. # Load settings
  965. self.loadSettings()
  966. # ----------------------------------------------------------------------------------------------------
  967. # Disable bridges if not enabled in settings
  968. # NOTE: We Assume win32 carla build will not run win64 plugins
  969. if (WINDOWS and not kIs64bit) or not host.showPluginBridges:
  970. self.ui.ch_native.setChecked(True)
  971. self.ui.ch_native.setEnabled(False)
  972. self.ui.ch_native.setVisible(False)
  973. self.ui.ch_bridged.setChecked(False)
  974. self.ui.ch_bridged.setEnabled(False)
  975. self.ui.ch_bridged.setVisible(False)
  976. self.ui.ch_bridged_wine.setChecked(False)
  977. self.ui.ch_bridged_wine.setEnabled(False)
  978. self.ui.ch_bridged_wine.setVisible(False)
  979. self.ui.l_arch.setVisible(False)
  980. elif not host.showWineBridges:
  981. self.ui.ch_bridged_wine.setChecked(False)
  982. self.ui.ch_bridged_wine.setEnabled(False)
  983. self.ui.ch_bridged_wine.setVisible(False)
  984. # ----------------------------------------------------------------------------------------------------
  985. # Set-up connections
  986. self.finished.connect(self.slot_saveSettings)
  987. self.ui.b_add.clicked.connect(self.slot_addPlugin)
  988. self.ui.b_cancel.clicked.connect(self.reject)
  989. self.ui.b_refresh.clicked.connect(self.slot_refreshPlugins)
  990. self.ui.tb_filters.clicked.connect(self.slot_maybeShowFilters)
  991. self.ui.lineEdit.textChanged.connect(self.slot_checkFilters)
  992. self.ui.tableWidget.currentCellChanged.connect(self.slot_checkPlugin)
  993. self.ui.tableWidget.cellDoubleClicked.connect(self.slot_addPlugin)
  994. self.ui.ch_effects.clicked.connect(self.slot_checkFilters)
  995. self.ui.ch_instruments.clicked.connect(self.slot_checkFilters)
  996. self.ui.ch_midi.clicked.connect(self.slot_checkFilters)
  997. self.ui.ch_other.clicked.connect(self.slot_checkFilters)
  998. self.ui.ch_internal.clicked.connect(self.slot_checkFilters)
  999. self.ui.ch_ladspa.clicked.connect(self.slot_checkFilters)
  1000. self.ui.ch_dssi.clicked.connect(self.slot_checkFilters)
  1001. self.ui.ch_lv2.clicked.connect(self.slot_checkFilters)
  1002. self.ui.ch_vst.clicked.connect(self.slot_checkFilters)
  1003. self.ui.ch_kits.clicked.connect(self.slot_checkFilters)
  1004. self.ui.ch_native.clicked.connect(self.slot_checkFilters)
  1005. self.ui.ch_bridged.clicked.connect(self.slot_checkFilters)
  1006. self.ui.ch_bridged_wine.clicked.connect(self.slot_checkFilters)
  1007. self.ui.ch_rtsafe.clicked.connect(self.slot_checkFilters)
  1008. self.ui.ch_gui.clicked.connect(self.slot_checkFilters)
  1009. self.ui.ch_stereo.clicked.connect(self.slot_checkFilters)
  1010. # ----------------------------------------------------------------------------------------------------
  1011. # Post-connect setup
  1012. self._reAddPlugins()
  1013. # --------------------------------------------------------------------------------------------------------
  1014. @pyqtSlot()
  1015. def slot_addPlugin(self):
  1016. if self.ui.tableWidget.currentRow() >= 0:
  1017. self.fRetPlugin = self.ui.tableWidget.item(self.ui.tableWidget.currentRow(), 0).data(Qt.UserRole)
  1018. self.accept()
  1019. else:
  1020. self.reject()
  1021. @pyqtSlot(int)
  1022. def slot_checkPlugin(self, row):
  1023. self.ui.b_add.setEnabled(row >= 0)
  1024. @pyqtSlot()
  1025. def slot_checkFilters(self):
  1026. self._checkFilters()
  1027. @pyqtSlot()
  1028. def slot_maybeShowFilters(self):
  1029. self._showFilters(not self.ui.frame.isVisible())
  1030. @pyqtSlot()
  1031. def slot_refreshPlugins(self):
  1032. if PluginRefreshW(self, self.host).exec_():
  1033. self._reAddPlugins()
  1034. if self.fRealParent:
  1035. self.fRealParent.setLoadRDFsNeeded()
  1036. # --------------------------------------------------------------------------------------------------------
  1037. @pyqtSlot()
  1038. def slot_saveSettings(self):
  1039. settings = QSettings("falkTX", "CarlaDatabase2")
  1040. settings.setValue("PluginDatabase/Geometry", self.saveGeometry())
  1041. settings.setValue("PluginDatabase/TableGeometry%s" % ("_5" if config_UseQt5 else "_4"), self.ui.tableWidget.horizontalHeader().saveState())
  1042. settings.setValue("PluginDatabase/ShowFilters", (self.ui.tb_filters.arrowType() == Qt.UpArrow))
  1043. settings.setValue("PluginDatabase/ShowEffects", self.ui.ch_effects.isChecked())
  1044. settings.setValue("PluginDatabase/ShowInstruments", self.ui.ch_instruments.isChecked())
  1045. settings.setValue("PluginDatabase/ShowMIDI", self.ui.ch_midi.isChecked())
  1046. settings.setValue("PluginDatabase/ShowOther", self.ui.ch_other.isChecked())
  1047. settings.setValue("PluginDatabase/ShowInternal", self.ui.ch_internal.isChecked())
  1048. settings.setValue("PluginDatabase/ShowLADSPA", self.ui.ch_ladspa.isChecked())
  1049. settings.setValue("PluginDatabase/ShowDSSI", self.ui.ch_dssi.isChecked())
  1050. settings.setValue("PluginDatabase/ShowLV2", self.ui.ch_lv2.isChecked())
  1051. settings.setValue("PluginDatabase/ShowVST2", self.ui.ch_vst.isChecked())
  1052. settings.setValue("PluginDatabase/ShowKits", self.ui.ch_kits.isChecked())
  1053. settings.setValue("PluginDatabase/ShowNative", self.ui.ch_native.isChecked())
  1054. settings.setValue("PluginDatabase/ShowBridged", self.ui.ch_bridged.isChecked())
  1055. settings.setValue("PluginDatabase/ShowBridgedWine", self.ui.ch_bridged_wine.isChecked())
  1056. settings.setValue("PluginDatabase/ShowRtSafe", self.ui.ch_rtsafe.isChecked())
  1057. settings.setValue("PluginDatabase/ShowHasGUI", self.ui.ch_gui.isChecked())
  1058. settings.setValue("PluginDatabase/ShowStereoOnly", self.ui.ch_stereo.isChecked())
  1059. settings.setValue("PluginDatabase/SearchText", self.ui.lineEdit.text())
  1060. # --------------------------------------------------------------------------------------------------------
  1061. def loadSettings(self):
  1062. settings = QSettings("falkTX", "CarlaDatabase2")
  1063. self.restoreGeometry(settings.value("PluginDatabase/Geometry", b""))
  1064. self.ui.ch_effects.setChecked(settings.value("PluginDatabase/ShowEffects", True, type=bool))
  1065. self.ui.ch_instruments.setChecked(settings.value("PluginDatabase/ShowInstruments", True, type=bool))
  1066. self.ui.ch_midi.setChecked(settings.value("PluginDatabase/ShowMIDI", True, type=bool))
  1067. self.ui.ch_other.setChecked(settings.value("PluginDatabase/ShowOther", True, type=bool))
  1068. self.ui.ch_internal.setChecked(settings.value("PluginDatabase/ShowInternal", True, type=bool))
  1069. self.ui.ch_ladspa.setChecked(settings.value("PluginDatabase/ShowLADSPA", True, type=bool))
  1070. self.ui.ch_dssi.setChecked(settings.value("PluginDatabase/ShowDSSI", True, type=bool))
  1071. self.ui.ch_lv2.setChecked(settings.value("PluginDatabase/ShowLV2", True, type=bool))
  1072. self.ui.ch_vst.setChecked(settings.value("PluginDatabase/ShowVST2", True, type=bool))
  1073. self.ui.ch_kits.setChecked(settings.value("PluginDatabase/ShowKits", True, type=bool))
  1074. self.ui.ch_native.setChecked(settings.value("PluginDatabase/ShowNative", True, type=bool))
  1075. self.ui.ch_bridged.setChecked(settings.value("PluginDatabase/ShowBridged", True, type=bool))
  1076. self.ui.ch_bridged_wine.setChecked(settings.value("PluginDatabase/ShowBridgedWine", True, type=bool))
  1077. self.ui.ch_rtsafe.setChecked(settings.value("PluginDatabase/ShowRtSafe", False, type=bool))
  1078. self.ui.ch_gui.setChecked(settings.value("PluginDatabase/ShowHasGUI", False, type=bool))
  1079. self.ui.ch_stereo.setChecked(settings.value("PluginDatabase/ShowStereoOnly", False, type=bool))
  1080. self.ui.lineEdit.setText(settings.value("PluginDatabase/SearchText", "", type=str))
  1081. tableGeometry = settings.value("PluginDatabase/TableGeometry%s" % ("_5" if config_UseQt5 else "_4"))
  1082. if tableGeometry:
  1083. self.ui.tableWidget.horizontalHeader().restoreState(tableGeometry)
  1084. else:
  1085. self.ui.tableWidget.sortByColumn(0, Qt.AscendingOrder)
  1086. self._showFilters(settings.value("PluginDatabase/ShowFilters", False, type=bool))
  1087. # --------------------------------------------------------------------------------------------------------
  1088. def _checkFilters(self):
  1089. text = self.ui.lineEdit.text().lower()
  1090. hideEffects = not self.ui.ch_effects.isChecked()
  1091. hideInstruments = not self.ui.ch_instruments.isChecked()
  1092. hideMidi = not self.ui.ch_midi.isChecked()
  1093. hideOther = not self.ui.ch_other.isChecked()
  1094. hideInternal = not self.ui.ch_internal.isChecked()
  1095. hideLadspa = not self.ui.ch_ladspa.isChecked()
  1096. hideDssi = not self.ui.ch_dssi.isChecked()
  1097. hideLV2 = not self.ui.ch_lv2.isChecked()
  1098. hideVST2 = not self.ui.ch_vst.isChecked()
  1099. hideKits = not self.ui.ch_kits.isChecked()
  1100. hideNative = not self.ui.ch_native.isChecked()
  1101. hideBridged = not self.ui.ch_bridged.isChecked()
  1102. hideBridgedWine = not self.ui.ch_bridged_wine.isChecked()
  1103. hideNonRtSafe = self.ui.ch_rtsafe.isChecked()
  1104. hideNonGui = self.ui.ch_gui.isChecked()
  1105. hideNonStereo = self.ui.ch_stereo.isChecked()
  1106. if HAIKU or LINUX or MACOS:
  1107. nativeBins = [BINARY_POSIX32, BINARY_POSIX64]
  1108. wineBins = [BINARY_WIN32, BINARY_WIN64]
  1109. elif WINDOWS:
  1110. nativeBins = [BINARY_WIN32, BINARY_WIN64]
  1111. wineBins = []
  1112. else:
  1113. nativeBins = []
  1114. wineBins = []
  1115. rowCount = self.ui.tableWidget.rowCount()
  1116. for i in range(self.fLastTableIndex):
  1117. plugin = self.ui.tableWidget.item(i, 0).data(Qt.UserRole)
  1118. aIns = plugin['audio.ins']
  1119. aOuts = plugin['audio.outs']
  1120. mIns = plugin['midi.ins']
  1121. mOuts = plugin['midi.outs']
  1122. ptype = self.ui.tableWidget.item(i, 12).text()
  1123. isSynth = bool(plugin['hints'] & PLUGIN_IS_SYNTH)
  1124. isEffect = bool(aIns > 0 < aOuts and not isSynth)
  1125. isMidi = bool(aIns == 0 and aOuts == 0 and mIns > 0 < mOuts)
  1126. isKit = bool(ptype in ("SF2", "SFZ"))
  1127. isOther = bool(not (isEffect or isSynth or isMidi or isKit))
  1128. isNative = bool(plugin['build'] == BINARY_NATIVE)
  1129. isRtSafe = bool(plugin['hints'] & PLUGIN_IS_RTSAFE)
  1130. isStereo = bool(aIns == 2 and aOuts == 2) or (isSynth and aOuts == 2)
  1131. hasGui = bool(plugin['hints'] & PLUGIN_HAS_CUSTOM_UI)
  1132. isBridged = bool(not isNative and plugin['build'] in nativeBins)
  1133. isBridgedWine = bool(not isNative and plugin['build'] in wineBins)
  1134. if hideEffects and isEffect:
  1135. self.ui.tableWidget.hideRow(i)
  1136. elif hideInstruments and isSynth:
  1137. self.ui.tableWidget.hideRow(i)
  1138. elif hideMidi and isMidi:
  1139. self.ui.tableWidget.hideRow(i)
  1140. elif hideOther and isOther:
  1141. self.ui.tableWidget.hideRow(i)
  1142. elif hideKits and isKit:
  1143. self.ui.tableWidget.hideRow(i)
  1144. elif hideInternal and ptype == self.tr("Internal"):
  1145. self.ui.tableWidget.hideRow(i)
  1146. elif hideLadspa and ptype == "LADSPA":
  1147. self.ui.tableWidget.hideRow(i)
  1148. elif hideDssi and ptype == "DSSI":
  1149. self.ui.tableWidget.hideRow(i)
  1150. elif hideLV2 and ptype == "LV2":
  1151. self.ui.tableWidget.hideRow(i)
  1152. elif hideVST2 and ptype == "VST2":
  1153. self.ui.tableWidget.hideRow(i)
  1154. elif hideNative and isNative:
  1155. self.ui.tableWidget.hideRow(i)
  1156. elif hideBridged and isBridged:
  1157. self.ui.tableWidget.hideRow(i)
  1158. elif hideBridgedWine and isBridgedWine:
  1159. self.ui.tableWidget.hideRow(i)
  1160. elif hideNonRtSafe and not isRtSafe:
  1161. self.ui.tableWidget.hideRow(i)
  1162. elif hideNonGui and not hasGui:
  1163. self.ui.tableWidget.hideRow(i)
  1164. elif hideNonStereo and not isStereo:
  1165. self.ui.tableWidget.hideRow(i)
  1166. elif (text and not (
  1167. text in self.ui.tableWidget.item(i, 0).text().lower() or
  1168. text in self.ui.tableWidget.item(i, 1).text().lower() or
  1169. text in self.ui.tableWidget.item(i, 2).text().lower() or
  1170. text in self.ui.tableWidget.item(i, 3).text().lower() or
  1171. text in self.ui.tableWidget.item(i, 13).text().lower())):
  1172. self.ui.tableWidget.hideRow(i)
  1173. else:
  1174. self.ui.tableWidget.showRow(i)
  1175. # --------------------------------------------------------------------------------------------------------
  1176. def _showFilters(self, yesNo):
  1177. self.ui.tb_filters.setArrowType(Qt.UpArrow if yesNo else Qt.DownArrow)
  1178. self.ui.frame.setVisible(yesNo)
  1179. # --------------------------------------------------------------------------------------------------------
  1180. def _addPluginToTable(self, plugin, ptype):
  1181. if plugin['API'] != PLUGIN_QUERY_API_VERSION and ptype == self.tr("Internal"):
  1182. return
  1183. if ptype in (self.tr("Internal"), "LV2", "SF2", "SFZ"):
  1184. plugin['build'] = BINARY_NATIVE
  1185. index = self.fLastTableIndex
  1186. if plugin['build'] == BINARY_NATIVE:
  1187. bridgeText = self.tr("No")
  1188. else:
  1189. if WINDOWS:
  1190. if plugin['build'] == BINARY_WIN32:
  1191. typeText = "32bit"
  1192. elif plugin['build'] == BINARY_WIN64:
  1193. typeText = "64bit"
  1194. else:
  1195. typeText = self.tr("Unknown")
  1196. else:
  1197. if plugin['build'] == BINARY_POSIX32:
  1198. typeText = "32bit"
  1199. elif plugin['build'] == BINARY_POSIX64:
  1200. typeText = "64bit"
  1201. elif plugin['build'] == BINARY_WIN32:
  1202. typeText = "Windows 32bit"
  1203. elif plugin['build'] == BINARY_WIN64:
  1204. typeText = "Windows 64bit"
  1205. else:
  1206. typeText = self.tr("Unknown")
  1207. bridgeText = self.tr("Yes (%s)" % typeText)
  1208. self.ui.tableWidget.setItem(index, 0, QTableWidgetItem(str(plugin['name'])))
  1209. self.ui.tableWidget.setItem(index, 1, QTableWidgetItem(str(plugin['label'])))
  1210. self.ui.tableWidget.setItem(index, 2, QTableWidgetItem(str(plugin['maker'])))
  1211. self.ui.tableWidget.setItem(index, 3, QTableWidgetItem(str(plugin['uniqueId'])))
  1212. self.ui.tableWidget.setItem(index, 4, QTableWidgetItem(str(plugin['audio.ins'])))
  1213. self.ui.tableWidget.setItem(index, 5, QTableWidgetItem(str(plugin['audio.outs'])))
  1214. self.ui.tableWidget.setItem(index, 6, QTableWidgetItem(str(plugin['parameters.ins'])))
  1215. self.ui.tableWidget.setItem(index, 7, QTableWidgetItem(str(plugin['parameters.outs'])))
  1216. self.ui.tableWidget.setItem(index, 9, QTableWidgetItem(self.tr("Yes") if (plugin['hints'] & PLUGIN_HAS_CUSTOM_UI) else self.tr("No")))
  1217. self.ui.tableWidget.setItem(index, 10, QTableWidgetItem(self.tr("Yes") if (plugin['hints'] & PLUGIN_IS_SYNTH) else self.tr("No")))
  1218. self.ui.tableWidget.setItem(index, 11, QTableWidgetItem(bridgeText))
  1219. self.ui.tableWidget.setItem(index, 12, QTableWidgetItem(ptype))
  1220. self.ui.tableWidget.setItem(index, 13, QTableWidgetItem(str(plugin['filename'])))
  1221. self.ui.tableWidget.item(index, 0).setData(Qt.UserRole, plugin)
  1222. self.fLastTableIndex += 1
  1223. # --------------------------------------------------------------------------------------------------------
  1224. def _reAddInternalHelper(self, settingsDB, ptype, path):
  1225. if ptype == PLUGIN_INTERNAL:
  1226. ptypeStr = "Internal"
  1227. ptypeStrTr = self.tr("Internal")
  1228. elif ptype == PLUGIN_LV2:
  1229. ptypeStr = "LV2"
  1230. ptypeStrTr = ptypeStr
  1231. #elif ptype == PLUGIN_SFZ:
  1232. #ptypeStr = "SFZ"
  1233. #ptypeStrTr = ptypeStr
  1234. else:
  1235. return 0
  1236. plugins = toList(settingsDB.value("Plugins/" + ptypeStr, []))
  1237. pluginCount = settingsDB.value("PluginCount/" + ptypeStr, 0, type=int)
  1238. pluginCountNew = gCarla.utils.get_cached_plugin_count(ptype, path)
  1239. if pluginCountNew != pluginCount or (len(plugins) > 0 and plugins[0]['API'] != PLUGIN_QUERY_API_VERSION):
  1240. plugins = []
  1241. pluginCount = pluginCountNew
  1242. QApplication.processEvents(QEventLoop.ExcludeUserInputEvents, 50)
  1243. for i in range(pluginCountNew):
  1244. descInfo = gCarla.utils.get_cached_plugin_info(ptype, i)
  1245. if not descInfo['valid']:
  1246. continue
  1247. info = checkPluginCached(descInfo, ptype)
  1248. plugins.append(info)
  1249. if i % 50 == 0:
  1250. QApplication.processEvents(QEventLoop.ExcludeUserInputEvents, 50)
  1251. settingsDB.setValue("Plugins/" + ptypeStr, plugins)
  1252. settingsDB.setValue("PluginCount/" + ptypeStr, pluginCount)
  1253. # prepare rows in advance
  1254. self.ui.tableWidget.setRowCount(self.fLastTableIndex + len(plugins))
  1255. for plugin in plugins:
  1256. self._addPluginToTable(plugin, ptypeStrTr)
  1257. return pluginCount
  1258. def _reAddPlugins(self):
  1259. settingsDB = QSettings("falkTX", "CarlaPlugins4")
  1260. for x in range(self.ui.tableWidget.rowCount()):
  1261. self.ui.tableWidget.removeRow(0)
  1262. self.fLastTableIndex = 0
  1263. self.ui.tableWidget.setSortingEnabled(False)
  1264. settings = QSettings("falkTX", "Carla2")
  1265. LV2_PATH = splitter.join(toList(settings.value(CARLA_KEY_PATHS_LV2, CARLA_DEFAULT_LV2_PATH)))
  1266. del settings
  1267. # ----------------------------------------------------------------------------------------------------
  1268. # plugins handled through backend
  1269. internalCount = self._reAddInternalHelper(settingsDB, PLUGIN_INTERNAL, "")
  1270. lv2Count = self._reAddInternalHelper(settingsDB, PLUGIN_LV2, LV2_PATH)
  1271. # ----------------------------------------------------------------------------------------------------
  1272. # LADSPA
  1273. ladspaPlugins = []
  1274. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_native", []))
  1275. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_posix32", []))
  1276. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_posix64", []))
  1277. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_win32", []))
  1278. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_win64", []))
  1279. # ----------------------------------------------------------------------------------------------------
  1280. # DSSI
  1281. dssiPlugins = []
  1282. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_native", []))
  1283. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_posix32", []))
  1284. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_posix64", []))
  1285. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_win32", []))
  1286. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_win64", []))
  1287. # ----------------------------------------------------------------------------------------------------
  1288. # VST2
  1289. vst2Plugins = []
  1290. vst2Plugins += toList(settingsDB.value("Plugins/VST2_native", []))
  1291. vst2Plugins += toList(settingsDB.value("Plugins/VST2_posix32", []))
  1292. vst2Plugins += toList(settingsDB.value("Plugins/VST2_posix64", []))
  1293. vst2Plugins += toList(settingsDB.value("Plugins/VST2_win32", []))
  1294. vst2Plugins += toList(settingsDB.value("Plugins/VST2_win64", []))
  1295. # ----------------------------------------------------------------------------------------------------
  1296. # Kits
  1297. sf2s = toList(settingsDB.value("Plugins/SF2", []))
  1298. sfzs = toList(settingsDB.value("Plugins/SFZ", []))
  1299. # ----------------------------------------------------------------------------------------------------
  1300. # count plugins first, so we can create rows in advance
  1301. ladspaCount = 0
  1302. dssiCount = 0
  1303. vstCount = 0
  1304. sf2Count = 0
  1305. sfzCount = 0
  1306. for plugins in ladspaPlugins:
  1307. ladspaCount += len(plugins)
  1308. for plugins in dssiPlugins:
  1309. dssiCount += len(plugins)
  1310. for plugins in vst2Plugins:
  1311. vstCount += len(plugins)
  1312. for plugins in sf2s:
  1313. sf2Count += len(plugins)
  1314. sfzCount += len(sfzs)
  1315. self.ui.tableWidget.setRowCount(self.fLastTableIndex+ladspaCount+dssiCount+vstCount+sf2Count+sfzCount)
  1316. self.ui.label.setText(self.tr("Have %i Internal, %i LADSPA, %i DSSI, %i LV2 and %i VST plugins, plus %i Sound Kits" % (
  1317. internalCount, ladspaCount, dssiCount, lv2Count, vstCount, sf2Count+sfzCount)))
  1318. # ----------------------------------------------------------------------------------------------------
  1319. # now add all plugins to the table
  1320. for plugins in ladspaPlugins:
  1321. for plugin in plugins:
  1322. self._addPluginToTable(plugin, "LADSPA")
  1323. for plugins in dssiPlugins:
  1324. for plugin in plugins:
  1325. self._addPluginToTable(plugin, "DSSI")
  1326. for plugins in vst2Plugins:
  1327. for plugin in plugins:
  1328. self._addPluginToTable(plugin, "VST2")
  1329. for sf2 in sf2s:
  1330. for sf2_i in sf2:
  1331. self._addPluginToTable(sf2_i, "SF2")
  1332. for sfz in sfzs:
  1333. self._addPluginToTable(sfz, "SFZ")
  1334. # ----------------------------------------------------------------------------------------------------
  1335. self.ui.tableWidget.setSortingEnabled(True)
  1336. self._checkFilters()
  1337. # --------------------------------------------------------------------------------------------------------
  1338. def done(self, r):
  1339. QDialog.done(self, r)
  1340. self.close()
  1341. # ----------------------------------------------------------------------------------------------------------------------
  1342. # Jack Application Dialog
  1343. class JackApplicationW(QDialog):
  1344. SESSION_MGR_NONE = 0
  1345. SESSION_MGR_AUTO = 1
  1346. SESSION_MGR_JACK = 2
  1347. SESSION_MGR_LADISH = 3
  1348. SESSION_MGR_NSM = 4
  1349. FLAG_CONTROL_WINDOW = 0x01
  1350. FLAG_CAPTURE_FIRST_WINDOW = 0x02
  1351. FLAG_BUFFERS_ADDITION_MODE = 0x10
  1352. def __init__(self, parent, host):
  1353. QDialog.__init__(self, parent)
  1354. self.host = host
  1355. self.ui = ui_carla_add_jack.Ui_Dialog()
  1356. self.ui.setupUi(self)
  1357. if False:
  1358. # kdevelop likes this :)
  1359. self.host = host = CarlaHostNull()
  1360. self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
  1361. # --------------------------------------------------------------------------------------------------------------
  1362. # Load settings
  1363. self.loadSettings()
  1364. # --------------------------------------------------------------------------------------------------------------
  1365. # Set-up connections
  1366. self.finished.connect(self.slot_saveSettings)
  1367. self.ui.le_command.textChanged.connect(self.slot_commandChanged)
  1368. # ------------------------------------------------------------------------------------------------------------------
  1369. def getCommandAndFlags(self):
  1370. name = self.ui.le_name.text()
  1371. command = self.ui.le_command.text()
  1372. smgr = self.SESSION_MGR_NONE
  1373. flags = 0x0
  1374. if not name:
  1375. name = os.path.basename(command.split(" ",1)[0])
  1376. # TODO finalize flag definitions
  1377. uiSessionMgrIndex = self.ui.cb_session_mgr.currentIndex()
  1378. if uiSessionMgrIndex == 1:
  1379. smgr = self.SESSION_MGR_AUTO
  1380. elif uiSessionMgrIndex == 2:
  1381. smgr = self.SESSION_MGR_LADISH
  1382. #elif uiSessionMgrIndex == 2:
  1383. #smgr = self.SESSION_MGR_NSM
  1384. if self.ui.cb_manage_window.isChecked():
  1385. flags |= self.FLAG_CONTROL_WINDOW
  1386. if self.ui.cb_capture_first_window.isChecked():
  1387. flags |= self.FLAG_CAPTURE_FIRST_WINDOW
  1388. if self.ui.cb_buffers_addition_mode.isChecked():
  1389. flags |= self.FLAG_BUFFERS_ADDITION_MODE
  1390. baseIntVal = ord('0')
  1391. labelSetup = "%s%s%s%s%s%s" % (chr(baseIntVal+self.ui.sb_audio_ins.value()),
  1392. chr(baseIntVal+self.ui.sb_audio_outs.value()),
  1393. chr(baseIntVal+self.ui.sb_midi_ins.value()),
  1394. chr(baseIntVal+self.ui.sb_midi_outs.value()),
  1395. chr(baseIntVal+smgr),
  1396. chr(baseIntVal+flags))
  1397. return (command, name, labelSetup)
  1398. def loadSettings(self):
  1399. settings = QSettings("falkTX", "CarlaAddJackApp")
  1400. command = settings.value("Command", "", type=str)
  1401. self.ui.le_command.setText(command)
  1402. self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(len(command) > 0)
  1403. self.ui.le_name.setText(settings.value("Name", "", type=str))
  1404. self.ui.sb_audio_ins.setValue(settings.value("NumAudioIns", 2, type=int))
  1405. self.ui.sb_audio_outs.setValue(settings.value("NumAudioOuts", 2, type=int))
  1406. self.ui.sb_midi_ins.setValue(settings.value("NumMidiIns", 0, type=int))
  1407. self.ui.sb_midi_outs.setValue(settings.value("NumMidiOuts", 0, type=int))
  1408. self.ui.cb_manage_window.setChecked(settings.value("ManageWindow", True, type=bool))
  1409. # ------------------------------------------------------------------------------------------------------------------
  1410. @pyqtSlot(str)
  1411. def slot_commandChanged(self, text):
  1412. self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(len(text) > 0)
  1413. @pyqtSlot()
  1414. def slot_saveSettings(self):
  1415. settings = QSettings("falkTX", "CarlaAddJackApp")
  1416. settings.setValue("Command", self.ui.le_command.text())
  1417. settings.setValue("Name", self.ui.le_name.text())
  1418. settings.setValue("NumAudioIns", self.ui.sb_audio_ins.value())
  1419. settings.setValue("NumAudioOuts", self.ui.sb_audio_outs.value())
  1420. settings.setValue("NumMidiIns", self.ui.sb_midi_ins.value())
  1421. settings.setValue("NumMidiOuts", self.ui.sb_midi_outs.value())
  1422. settings.setValue("ManageWindow", self.ui.cb_manage_window.isChecked())
  1423. # ------------------------------------------------------------------------------------------------------------------
  1424. def done(self, r):
  1425. QDialog.done(self, r)
  1426. self.close()
  1427. # ----------------------------------------------------------------------------------------------------------------------
  1428. # Main
  1429. if __name__ == '__main__':
  1430. from carla_app import CarlaApplication
  1431. from carla_host import initHost, loadHostSettings
  1432. initName, libPrefix = handleInitialCommandLineArguments(__file__ if "__file__" in dir() else None)
  1433. app = CarlaApplication("Carla2-Database", libPrefix)
  1434. host = initHost("Carla2-Database", libPrefix, False, False, False)
  1435. loadHostSettings(host)
  1436. gui = PluginDatabaseW(None, host)
  1437. gui.show()
  1438. app.exit_exec()
  1439. # ------------------------------------------------------------------------------------------------------------