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.

2061 lines
81KB

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