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.

1695 lines
64KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla plugin database code
  4. # Copyright (C) 2011-2014 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, QTableWidgetItem
  27. else:
  28. from PyQt4.QtCore import pyqtSignal, pyqtSlot, Qt, QThread, QSettings
  29. from PyQt4.QtGui import QDialog, QTableWidgetItem
  30. # ------------------------------------------------------------------------------------------------------------
  31. # Imports (Custom)
  32. import ui_carla_database
  33. import ui_carla_refresh
  34. from carla_shared import *
  35. # ------------------------------------------------------------------------------------------------------------
  36. # Try Import LADSPA-RDF
  37. try:
  38. import ladspa_rdf
  39. import json
  40. haveLRDF = True
  41. except:
  42. qWarning("LRDF Support not available (LADSPA-RDF will be disabled)")
  43. haveLRDF = False
  44. # ------------------------------------------------------------------------------------------------------------
  45. # Set LADSPA-RDF Path
  46. if haveLRDF and readEnvVars:
  47. LADSPA_RDF_PATH_env = os.getenv("LADSPA_RDF_PATH")
  48. if LADSPA_RDF_PATH_env:
  49. ladspa_rdf.set_rdf_path(LADSPA_RDF_PATH_env.split(splitter))
  50. del LADSPA_RDF_PATH_env
  51. # ------------------------------------------------------------------------------------------------------------
  52. # Plugin Query (helper functions)
  53. def findBinaries(binPath, OS):
  54. binaries = []
  55. if OS == "WINDOWS":
  56. extensions = (".dll",)
  57. elif OS == "MACOS":
  58. extensions = (".dylib", ".so")
  59. else:
  60. extensions = (".so",)
  61. for root, dirs, files in os.walk(binPath):
  62. for name in [name for name in files if name.lower().endswith(extensions)]:
  63. binaries.append(os.path.join(root, name))
  64. return binaries
  65. def findLV2Bundles(bundlePath):
  66. bundles = []
  67. for root, dirs, files in os.walk(bundlePath):
  68. if os.path.exists(os.path.join(root, "manifest.ttl")):
  69. bundles.append(root)
  70. return bundles
  71. def findMacVSTBundles(bundlePath):
  72. bundles = []
  73. for root, dirs, files in os.walk(bundlePath):
  74. for name in [name for name in dirs if name.lower().endswith(".vst")]:
  75. bundles.append(os.path.join(root, name))
  76. return bundles
  77. def findFilenames(filePath, stype):
  78. filenames = []
  79. if stype == "csd":
  80. extensions = (".csd",)
  81. elif stype == "gig":
  82. extensions = (".gig",)
  83. elif stype == "sf2":
  84. extensions = (".sf2",)
  85. elif stype == "sfz":
  86. extensions = (".sfz",)
  87. else:
  88. return []
  89. for root, dirs, files in os.walk(filePath):
  90. for name in [name for name in files if name.lower().endswith(extensions)]:
  91. filenames.append(os.path.join(root, name))
  92. return filenames
  93. # ------------------------------------------------------------------------------------------------------------
  94. # Plugin Query
  95. PLUGIN_QUERY_API_VERSION = 3
  96. PyPluginInfo = {
  97. 'API': PLUGIN_QUERY_API_VERSION,
  98. 'build': BINARY_NONE,
  99. 'type': PLUGIN_NONE,
  100. 'hints': 0x0,
  101. 'filename': "",
  102. 'name': "",
  103. 'label': "",
  104. 'maker': "",
  105. 'copyright': "",
  106. 'uniqueId': 0,
  107. 'audio.ins': 0,
  108. 'audio.outs': 0,
  109. 'audio.total': 0,
  110. 'midi.ins': 0,
  111. 'midi.outs': 0,
  112. 'midi.total': 0,
  113. 'parameters.ins': 0,
  114. 'parameters.outs': 0,
  115. 'parameters.total': 0,
  116. 'programs.total': 0
  117. }
  118. global gDiscoveryProcess
  119. gDiscoveryProcess = None
  120. def runCarlaDiscovery(itype, stype, filename, tool, isWine=False):
  121. if not os.path.exists(tool):
  122. qWarning("runCarlaDiscovery() - tool '%s' does not exist" % tool)
  123. return
  124. command = []
  125. if LINUX or MACOS:
  126. command.append("env")
  127. command.append("LANG=C")
  128. if isWine:
  129. command.append("WINEDEBUG=-all")
  130. command.append("wine")
  131. command.append(tool)
  132. command.append(stype)
  133. command.append(filename)
  134. global gDiscoveryProcess
  135. gDiscoveryProcess = Popen(command, stdout=PIPE)
  136. pinfo = None
  137. plugins = []
  138. fakeLabel = os.path.basename(filename).rsplit(".", 1)[0]
  139. while True:
  140. try:
  141. line = gDiscoveryProcess.stdout.readline().decode("utf-8", errors="ignore")
  142. except:
  143. print("ERROR: discovery readline failed")
  144. break
  145. # line is valid, strip it
  146. if line:
  147. line = line.strip()
  148. # line is invalid, try poll() again
  149. elif gDiscoveryProcess.poll() is None:
  150. continue
  151. # line is invalid and poll() failed, stop here
  152. else:
  153. break
  154. if line == "carla-discovery::init::-----------":
  155. pinfo = deepcopy(PyPluginInfo)
  156. pinfo['type'] = itype
  157. pinfo['filename'] = filename
  158. elif line == "carla-discovery::end::------------":
  159. if pinfo is not None:
  160. plugins.append(pinfo)
  161. del pinfo
  162. pinfo = None
  163. elif line == "Segmentation fault":
  164. print("carla-discovery::crash::%s crashed during discovery" % filename)
  165. elif line.startswith("err:module:import_dll Library"):
  166. print(line)
  167. elif line.startswith("carla-discovery::info::"):
  168. print("%s - %s" % (line, filename))
  169. elif line.startswith("carla-discovery::error::"):
  170. print("%s - %s" % (line, filename))
  171. elif line.startswith("carla-discovery::"):
  172. if pinfo == None:
  173. continue
  174. try:
  175. prop, value = line.replace("carla-discovery::", "").split("::", 1)
  176. except:
  177. continue
  178. if prop == "name":
  179. pinfo['name'] = value if value else fakeLabel
  180. elif prop == "label":
  181. pinfo['label'] = value if value else fakeLabel
  182. elif prop == "maker":
  183. pinfo['maker'] = value
  184. elif prop == "copyright":
  185. pinfo['copyright'] = value
  186. elif prop == "uniqueId":
  187. if value.isdigit(): pinfo['uniqueId'] = int(value)
  188. elif prop == "hints":
  189. if value.isdigit(): pinfo['hints'] = int(value)
  190. elif prop == "audio.ins":
  191. if value.isdigit(): pinfo['audio.ins'] = int(value)
  192. elif prop == "audio.outs":
  193. if value.isdigit(): pinfo['audio.outs'] = int(value)
  194. elif prop == "audio.total":
  195. if value.isdigit(): pinfo['audio.total'] = int(value)
  196. elif prop == "midi.ins":
  197. if value.isdigit(): pinfo['midi.ins'] = int(value)
  198. elif prop == "midi.outs":
  199. if value.isdigit(): pinfo['midi.outs'] = int(value)
  200. elif prop == "midi.total":
  201. if value.isdigit(): pinfo['midi.total'] = int(value)
  202. elif prop == "parameters.ins":
  203. if value.isdigit(): pinfo['parameters.ins'] = int(value)
  204. elif prop == "parameters.outs":
  205. if value.isdigit(): pinfo['parameters.outs'] = int(value)
  206. elif prop == "parameters.total":
  207. if value.isdigit(): pinfo['parameters.total'] = int(value)
  208. elif prop == "programs.total":
  209. if value.isdigit(): pinfo['programs.total'] = int(value)
  210. elif prop == "build":
  211. if value.isdigit(): pinfo['build'] = int(value)
  212. elif prop == "uri":
  213. if value:
  214. pinfo['label'] = value
  215. else:
  216. # cannot use empty URIs
  217. del pinfo
  218. pinfo = None
  219. continue
  220. # FIXME?
  221. tmp = gDiscoveryProcess
  222. gDiscoveryProcess = None
  223. del gDiscoveryProcess, tmp
  224. return plugins
  225. def killDiscovery():
  226. global gDiscoveryProcess
  227. if gDiscoveryProcess is not None:
  228. gDiscoveryProcess.kill()
  229. def checkPluginInternal(desc):
  230. plugins = []
  231. pinfo = deepcopy(PyPluginInfo)
  232. pinfo['build'] = BINARY_NATIVE
  233. pinfo['type'] = PLUGIN_INTERNAL
  234. pinfo['hints'] = desc['hints']
  235. pinfo['name'] = desc['name']
  236. pinfo['label'] = desc['label']
  237. pinfo['maker'] = desc['maker']
  238. pinfo['copyright'] = desc['copyright']
  239. pinfo['audio.ins'] = desc['audioIns']
  240. pinfo['audio.outs'] = desc['audioOuts']
  241. pinfo['audio.total'] = pinfo['audio.ins'] + pinfo['audio.outs']
  242. pinfo['midi.ins'] = desc['midiIns']
  243. pinfo['midi.outs'] = desc['midiOuts']
  244. pinfo['midi.total'] = pinfo['midi.ins'] + pinfo['midi.outs']
  245. pinfo['parameters.ins'] = desc['parameterIns']
  246. pinfo['parameters.outs'] = desc['parameterOuts']
  247. pinfo['parameters.total'] = pinfo['parameters.ins'] + pinfo['parameters.outs']
  248. plugins.append(pinfo)
  249. return plugins
  250. def checkPluginLADSPA(filename, tool, isWine=False):
  251. return runCarlaDiscovery(PLUGIN_LADSPA, "LADSPA", filename, tool, isWine)
  252. def checkPluginDSSI(filename, tool, isWine=False):
  253. return runCarlaDiscovery(PLUGIN_DSSI, "DSSI", filename, tool, isWine)
  254. def checkPluginLV2(filename, tool, isWine=False):
  255. return runCarlaDiscovery(PLUGIN_LV2, "LV2", filename, tool, isWine)
  256. def checkPluginVST(filename, tool, isWine=False):
  257. return runCarlaDiscovery(PLUGIN_VST, "VST", filename, tool, isWine)
  258. def checkPluginAU(filename, tool):
  259. return runCarlaDiscovery(PLUGIN_AU, "AU", filename, tool)
  260. def checkFileCSD(filename, tool):
  261. return runCarlaDiscovery(PLUGIN_FILE_CSD, "CSD", filename, tool)
  262. def checkFileGIG(filename, tool):
  263. return runCarlaDiscovery(PLUGIN_FILE_GIG, "GIG", filename, tool)
  264. def checkFileSF2(filename, tool):
  265. return runCarlaDiscovery(PLUGIN_FILE_SF2, "SF2", filename, tool)
  266. def checkFileSFZ(filename, tool):
  267. return runCarlaDiscovery(PLUGIN_FILE_SFZ, "SFZ", filename, tool)
  268. # ------------------------------------------------------------------------------------------------------------
  269. # Separate Thread for Plugin Search
  270. class SearchPluginsThread(QThread):
  271. pluginLook = pyqtSignal(int, str)
  272. def __init__(self, parent):
  273. QThread.__init__(self, parent)
  274. self.fContinueChecking = False
  275. self.fCheckNative = False
  276. self.fCheckPosix32 = False
  277. self.fCheckPosix64 = False
  278. self.fCheckWin32 = False
  279. self.fCheckWin64 = False
  280. self.fCheckLADSPA = False
  281. self.fCheckDSSI = False
  282. self.fCheckLV2 = False
  283. self.fCheckVST = False
  284. self.fCheckAU = False
  285. self.fCheckCSD = False
  286. self.fCheckGIG = False
  287. self.fCheckSF2 = False
  288. self.fCheckSFZ = False
  289. self.fToolNative = gCarla.discovery_native
  290. self.fCurCount = 0
  291. self.fCurPercentValue = 0
  292. self.fLastCheckValue = 0
  293. self.fSomethingChanged = False
  294. self.fLadspaPlugins = []
  295. self.fDssiPlugins = []
  296. self.fLv2Plugins = []
  297. self.fVstPlugins = []
  298. self.fAuPlugins = []
  299. self.fCsdFiles = []
  300. self.fKitPlugins = []
  301. print(gCarla.discovery_native)
  302. # -------------------------------------------------------------
  303. def hasSomethingChanged(self):
  304. return self.fSomethingChanged
  305. def setSearchBinaryTypes(self, native, posix32, posix64, win32, win64):
  306. self.fCheckNative = native
  307. self.fCheckPosix32 = posix32
  308. self.fCheckPosix64 = posix64
  309. self.fCheckWin32 = win32
  310. self.fCheckWin64 = win64
  311. def setSearchPluginTypes(self, ladspa, dssi, lv2, vst, au, csd, gig, sf2, sfz):
  312. self.fCheckLADSPA = ladspa
  313. self.fCheckDSSI = dssi
  314. self.fCheckLV2 = lv2
  315. self.fCheckVST = vst
  316. self.fCheckAU = au and MACOS
  317. self.fCheckCSD = csd
  318. self.fCheckGIG = gig
  319. self.fCheckSF2 = sf2
  320. self.fCheckSFZ = sfz
  321. def setSearchToolNative(self, tool):
  322. self.fToolNative = tool
  323. def stop(self):
  324. self.fContinueChecking = False
  325. def run(self):
  326. self.fContinueChecking = True
  327. self.fCurCount = 0
  328. pluginCount = 0
  329. settingsDB = QSettings("falkTX", "CarlaPlugins2")
  330. if self.fCheckLADSPA: pluginCount += 1
  331. if self.fCheckDSSI: pluginCount += 1
  332. if self.fCheckLV2: pluginCount += 1
  333. if self.fCheckVST: pluginCount += 1
  334. if self.fCheckAU: pluginCount += 1
  335. if self.fCheckNative:
  336. self.fCurCount += pluginCount
  337. if self.fCheckPosix32:
  338. self.fCurCount += pluginCount
  339. if self.fCheckPosix64:
  340. self.fCurCount += pluginCount
  341. if self.fCheckWin32:
  342. self.fCurCount += pluginCount
  343. if self.fCheckAU: self.fCurCount -= 1
  344. if self.fCheckWin64:
  345. self.fCurCount += pluginCount
  346. if self.fCheckAU: self.fCurCount -= 1
  347. if self.fCheckNative and self.fToolNative:
  348. if self.fCheckCSD: self.fCurCount += 1
  349. if self.fCheckGIG: self.fCurCount += 1
  350. if self.fCheckSF2: self.fCurCount += 1
  351. if self.fCheckSFZ: self.fCurCount += 1
  352. else:
  353. self.fCheckCSD = False
  354. self.fCheckGIG = False
  355. self.fCheckSF2 = False
  356. self.fCheckSFZ = False
  357. if self.fCurCount == 0:
  358. return
  359. self.fCurPercentValue = 100.0 / self.fCurCount
  360. self.fLastCheckValue = 0.0
  361. if HAIKU:
  362. OS = "HAIKU"
  363. elif LINUX:
  364. OS = "LINUX"
  365. elif MACOS:
  366. OS = "MACOS"
  367. elif WINDOWS:
  368. OS = "WINDOWS"
  369. else:
  370. OS = "UNKNOWN"
  371. if not self.fContinueChecking: return
  372. if self.fCheckLADSPA:
  373. checkValue = 0.0
  374. if haveLRDF:
  375. if self.fCheckNative: checkValue += 0.1
  376. if self.fCheckPosix32: checkValue += 0.1
  377. if self.fCheckPosix64: checkValue += 0.1
  378. if self.fCheckWin32: checkValue += 0.1
  379. if self.fCheckWin64: checkValue += 0.1
  380. rdfPadValue = self.fCurPercentValue * checkValue
  381. if self.fCheckNative:
  382. self._checkLADSPA(OS, self.fToolNative)
  383. settingsDB.setValue("Plugins/LADSPA_native", self.fLadspaPlugins)
  384. if not self.fContinueChecking: return
  385. if self.fCheckPosix32:
  386. self._checkLADSPA(OS, gCarla.discovery_posix32)
  387. settingsDB.setValue("Plugins/LADSPA_posix32", self.fLadspaPlugins)
  388. if not self.fContinueChecking: return
  389. if self.fCheckPosix64:
  390. self._checkLADSPA(OS, gCarla.discovery_posix64)
  391. settingsDB.setValue("Plugins/LADSPA_posix64", self.fLadspaPlugins)
  392. if not self.fContinueChecking: return
  393. if self.fCheckWin32:
  394. self._checkLADSPA("WINDOWS", gCarla.discovery_win32, not WINDOWS)
  395. settingsDB.setValue("Plugins/LADSPA_win32", self.fLadspaPlugins)
  396. if not self.fContinueChecking: return
  397. if self.fCheckWin64:
  398. self._checkLADSPA("WINDOWS", gCarla.discovery_win64, not WINDOWS)
  399. settingsDB.setValue("Plugins/LADSPA_win64", self.fLadspaPlugins)
  400. settingsDB.sync()
  401. if not self.fContinueChecking: return
  402. if haveLRDF and checkValue > 0:
  403. startValue = self.fLastCheckValue - rdfPadValue
  404. self._pluginLook(startValue, "LADSPA RDFs...")
  405. ladspaRdfInfo = ladspa_rdf.recheck_all_plugins(self, startValue, self.fCurPercentValue, checkValue)
  406. settingsDir = os.path.join(HOME, ".config", "falkTX")
  407. fdLadspa = open(os.path.join(settingsDir, "ladspa_rdf.db"), 'w')
  408. json.dump(ladspaRdfInfo, fdLadspa)
  409. fdLadspa.close()
  410. if not self.fContinueChecking: return
  411. if self.fCheckDSSI:
  412. if self.fCheckNative:
  413. self._checkDSSI(OS, self.fToolNative)
  414. settingsDB.setValue("Plugins/DSSI_native", self.fDssiPlugins)
  415. if not self.fContinueChecking: return
  416. if self.fCheckPosix32:
  417. self._checkDSSI(OS, gCarla.discovery_posix32)
  418. settingsDB.setValue("Plugins/DSSI_posix32", self.fDssiPlugins)
  419. if not self.fContinueChecking: return
  420. if self.fCheckPosix64:
  421. self._checkDSSI(OS, gCarla.discovery_posix64)
  422. settingsDB.setValue("Plugins/DSSI_posix64", self.fDssiPlugins)
  423. if not self.fContinueChecking: return
  424. if self.fCheckWin32:
  425. self._checkDSSI("WINDOWS", gCarla.discovery_win32, not WINDOWS)
  426. settingsDB.setValue("Plugins/DSSI_win32", self.fDssiPlugins)
  427. if not self.fContinueChecking: return
  428. if self.fCheckWin64:
  429. self._checkDSSI("WINDOWS", gCarla.discovery_win64, not WINDOWS)
  430. settingsDB.setValue("Plugins/DSSI_win64", self.fDssiPlugins)
  431. settingsDB.sync()
  432. if not self.fContinueChecking: return
  433. if self.fCheckLV2:
  434. if self.fCheckNative:
  435. self._checkLV2(self.fToolNative)
  436. settingsDB.setValue("Plugins/LV2_native", self.fLv2Plugins)
  437. if not self.fContinueChecking: return
  438. if self.fCheckPosix32:
  439. self._checkLV2(gCarla.discovery_posix32)
  440. settingsDB.setValue("Plugins/LV2_posix32", self.fLv2Plugins)
  441. if not self.fContinueChecking: return
  442. if self.fCheckPosix64:
  443. self._checkLV2(gCarla.discovery_posix64)
  444. settingsDB.setValue("Plugins/LV2_posix64", self.fLv2Plugins)
  445. if not self.fContinueChecking: return
  446. if self.fCheckWin32:
  447. self._checkLV2(gCarla.discovery_win32, not WINDOWS)
  448. settingsDB.setValue("Plugins/LV2_win32", self.fLv2Plugins)
  449. if not self.fContinueChecking: return
  450. if self.fCheckWin64:
  451. self._checkLV2(gCarla.discovery_win64, not WINDOWS)
  452. settingsDB.setValue("Plugins/LV2_win64", self.fLv2Plugins)
  453. settingsDB.sync()
  454. if not self.fContinueChecking: return
  455. if self.fCheckVST:
  456. if self.fCheckNative:
  457. self._checkVST(OS, self.fToolNative)
  458. settingsDB.setValue("Plugins/VST_native", self.fVstPlugins)
  459. if not self.fContinueChecking: return
  460. if self.fCheckPosix32:
  461. self._checkVST(OS, gCarla.discovery_posix32)
  462. settingsDB.setValue("Plugins/VST_posix32", self.fVstPlugins)
  463. if not self.fContinueChecking: return
  464. if self.fCheckPosix64:
  465. self._checkVST(OS, gCarla.discovery_posix64)
  466. settingsDB.setValue("Plugins/VST_posix64", self.fVstPlugins)
  467. if not self.fContinueChecking: return
  468. if self.fCheckWin32:
  469. self._checkVST("WINDOWS", gCarla.discovery_win32, not WINDOWS)
  470. settingsDB.setValue("Plugins/VST_win32", self.fVstPlugins)
  471. if not self.fContinueChecking: return
  472. if self.fCheckWin64:
  473. self._checkVST("WINDOWS", gCarla.discovery_win64, not WINDOWS)
  474. settingsDB.setValue("Plugins/VST_win64", self.fVstPlugins)
  475. settingsDB.sync()
  476. if not self.fContinueChecking: return
  477. if self.fCheckAU:
  478. if self.fCheckNative:
  479. self._checkAU(self.fToolNative)
  480. settingsDB.setValue("Plugins/AU_native", self.fAuPlugins)
  481. if not self.fContinueChecking: return
  482. if self.fCheckPosix32:
  483. self._checkAU(gCarla.discovery_posix32)
  484. settingsDB.setValue("Plugins/AU_posix32", self.fAuPlugins)
  485. if not self.fContinueChecking: return
  486. if self.fCheckPosix64:
  487. self._checkAU(gCarla.discovery_posix64)
  488. settingsDB.setValue("Plugins/AU_posix64", self.fAuPlugins)
  489. settingsDB.sync()
  490. if not self.fContinueChecking: return
  491. if self.fCheckCSD:
  492. self._checkCSD()
  493. settingsDB.setValue("Plugins/CSD", self.fCsdFiles)
  494. if not self.fContinueChecking: return
  495. if self.fCheckGIG:
  496. settings = QSettings()
  497. GIG_PATH = toList(settings.value("Paths/GIG", gCarla.DEFAULT_GIG_PATH))
  498. del settings
  499. self._checkKIT(GIG_PATH, "gig")
  500. settingsDB.setValue("Plugins/GIG", self.fKitPlugins)
  501. if not self.fContinueChecking: return
  502. if self.fCheckSF2:
  503. settings = QSettings()
  504. SF2_PATH = toList(settings.value("Paths/SF2", gCarla.DEFAULT_SF2_PATH))
  505. del settings
  506. self._checkKIT(SF2_PATH, "sf2")
  507. settingsDB.setValue("Plugins/SF2", self.fKitPlugins)
  508. if not self.fContinueChecking: return
  509. if self.fCheckSFZ:
  510. settings = QSettings()
  511. SFZ_PATH = toList(settings.value("Paths/SFZ", gCarla.DEFAULT_SFZ_PATH))
  512. del settings
  513. self._checkKIT(SFZ_PATH, "sfz")
  514. settingsDB.setValue("Plugins/SFZ", self.fKitPlugins)
  515. settingsDB.sync()
  516. def _checkLADSPA(self, OS, tool, isWine=False):
  517. ladspaBinaries = []
  518. self.fLadspaPlugins = []
  519. self._pluginLook(self.fLastCheckValue, "LADSPA plugins...")
  520. settings = QSettings()
  521. LADSPA_PATH = toList(settings.value("Paths/LADSPA", gCarla.DEFAULT_LADSPA_PATH))
  522. for iPATH in LADSPA_PATH:
  523. binaries = findBinaries(iPATH, OS)
  524. for binary in binaries:
  525. if binary not in ladspaBinaries:
  526. ladspaBinaries.append(binary)
  527. ladspaBinaries.sort()
  528. if not self.fContinueChecking: return
  529. for i in range(len(ladspaBinaries)):
  530. ladspa = ladspaBinaries[i]
  531. percent = ( float(i) / len(ladspaBinaries) ) * self.fCurPercentValue
  532. self._pluginLook((self.fLastCheckValue + percent) * 0.9, ladspa)
  533. plugins = checkPluginLADSPA(ladspa, tool, isWine)
  534. if plugins:
  535. self.fLadspaPlugins.append(plugins)
  536. self.fSomethingChanged = True
  537. if not self.fContinueChecking: break
  538. self.fLastCheckValue += self.fCurPercentValue
  539. def _checkDSSI(self, OS, tool, isWine=False):
  540. dssiBinaries = []
  541. self.fDssiPlugins = []
  542. self._pluginLook(self.fLastCheckValue, "DSSI plugins...")
  543. settings = QSettings()
  544. DSSI_PATH = toList(settings.value("Paths/DSSI", gCarla.DEFAULT_DSSI_PATH))
  545. for iPATH in DSSI_PATH:
  546. binaries = findBinaries(iPATH, OS)
  547. for binary in binaries:
  548. if binary not in dssiBinaries:
  549. dssiBinaries.append(binary)
  550. dssiBinaries.sort()
  551. if not self.fContinueChecking: return
  552. for i in range(len(dssiBinaries)):
  553. dssi = dssiBinaries[i]
  554. percent = ( float(i) / len(dssiBinaries) ) * self.fCurPercentValue
  555. self._pluginLook(self.fLastCheckValue + percent, dssi)
  556. plugins = checkPluginDSSI(dssi, tool, isWine)
  557. if plugins:
  558. self.fDssiPlugins.append(plugins)
  559. self.fSomethingChanged = True
  560. if not self.fContinueChecking: break
  561. self.fLastCheckValue += self.fCurPercentValue
  562. def _checkLV2(self, tool, isWine=False):
  563. lv2Bundles = []
  564. self.fLv2Plugins = []
  565. self._pluginLook(self.fLastCheckValue, "LV2 bundles...")
  566. settings = QSettings()
  567. LV2_PATH = toList(settings.value("Paths/LV2", gCarla.DEFAULT_LV2_PATH))
  568. for iPATH in LV2_PATH:
  569. bundles = findLV2Bundles(iPATH)
  570. for bundle in bundles:
  571. if bundle not in lv2Bundles:
  572. lv2Bundles.append(bundle)
  573. lv2Bundles.sort()
  574. if not self.fContinueChecking: return
  575. for i in range(len(lv2Bundles)):
  576. lv2 = lv2Bundles[i]
  577. percent = ( float(i) / len(lv2Bundles) ) * self.fCurPercentValue
  578. self._pluginLook(self.fLastCheckValue + percent, lv2)
  579. plugins = checkPluginLV2(lv2, tool, isWine)
  580. if plugins:
  581. self.fLv2Plugins.append(plugins)
  582. self.fSomethingChanged = True
  583. if not self.fContinueChecking: break
  584. self.fLastCheckValue += self.fCurPercentValue
  585. def _checkVST(self, OS, tool, isWine=False):
  586. vstBinaries = []
  587. self.fVstPlugins = []
  588. if MACOS and not isWine:
  589. self._pluginLook(self.fLastCheckValue, "VST bundles...")
  590. else:
  591. self._pluginLook(self.fLastCheckValue, "VST plugins...")
  592. settings = QSettings()
  593. VST_PATH = toList(settings.value("Paths/VST", gCarla.DEFAULT_VST_PATH))
  594. for iPATH in VST_PATH:
  595. if MACOS and not isWine:
  596. binaries = findMacVSTBundles(iPATH)
  597. else:
  598. binaries = findBinaries(iPATH, OS)
  599. for binary in binaries:
  600. if binary not in vstBinaries:
  601. vstBinaries.append(binary)
  602. vstBinaries.sort()
  603. if not self.fContinueChecking: return
  604. for i in range(len(vstBinaries)):
  605. vst = vstBinaries[i]
  606. percent = ( float(i) / len(vstBinaries) ) * self.fCurPercentValue
  607. self._pluginLook(self.fLastCheckValue + percent, vst)
  608. plugins = checkPluginVST(vst, tool, isWine)
  609. if plugins:
  610. self.fVstPlugins.append(plugins)
  611. self.fSomethingChanged = True
  612. if not self.fContinueChecking: break
  613. self.fLastCheckValue += self.fCurPercentValue
  614. def _checkAU(self, tool):
  615. auBinaries = []
  616. self.fAuPlugins = []
  617. # FIXME - this probably uses bundles
  618. self._pluginLook(self.fLastCheckValue, "AU plugins...")
  619. settings = QSettings()
  620. AU_PATH = toList(settings.value("Paths/AU", gCarla.DEFAULT_AU_PATH))
  621. for iPATH in AU_PATH:
  622. binaries = findBinaries(iPATH, "MACOS")
  623. for binary in binaries:
  624. if binary not in auBinaries:
  625. auBinaries.append(binary)
  626. auBinaries.sort()
  627. if not self.fContinueChecking: return
  628. for i in range(len(auBinaries)):
  629. au = auBinaries[i]
  630. percent = ( float(i) / len(auBinaries) ) * self.fCurPercentValue
  631. self._pluginLook(self.fLastCheckValue + percent, au)
  632. plugins = checkPluginAU(au, tool)
  633. if plugins:
  634. self.fAuPlugins.append(plugins)
  635. self.fSomethingChanged = True
  636. if not self.fContinueChecking: break
  637. self.fLastCheckValue += self.fCurPercentValue
  638. def _checkCSD(self):
  639. csdFiles = []
  640. self.fCsdFiles = []
  641. settings = QSettings()
  642. CSOUND_PATH = toList(settings.value("Paths/CSOUND", gCarla.DEFAULT_CSOUND_PATH))
  643. for iPATH in CSOUND_PATH:
  644. files = findFilenames(iPATH, "csd")
  645. for file_ in files:
  646. if file_ not in csdFiles:
  647. csdFiles.append(file_)
  648. csdFiles.sort()
  649. if not self.fContinueChecking: return
  650. for i in range(len(csdFiles)):
  651. csd = csdFiles[i]
  652. percent = ( float(i) / len(csdFiles) ) * self.fCurPercentValue
  653. self._pluginLook(self.fLastCheckValue + percent, csd)
  654. plugins = checkFileCSD(csd, self.fToolNative)
  655. if plugins:
  656. self.fCsdFiles.append(plugins)
  657. self.fSomethingChanged = True
  658. if not self.fContinueChecking: break
  659. self.fLastCheckValue += self.fCurPercentValue
  660. def _checkKIT(self, kitPATH, kitExtension):
  661. kitFiles = []
  662. self.fKitPlugins = []
  663. for iPATH in kitPATH:
  664. files = findFilenames(iPATH, kitExtension)
  665. for file_ in files:
  666. if file_ not in kitFiles:
  667. kitFiles.append(file_)
  668. kitFiles.sort()
  669. if not self.fContinueChecking: return
  670. for i in range(len(kitFiles)):
  671. kit = kitFiles[i]
  672. percent = ( float(i) / len(kitFiles) ) * self.fCurPercentValue
  673. self._pluginLook(self.fLastCheckValue + percent, kit)
  674. if kitExtension == "gig":
  675. plugins = checkFileGIG(kit, self.fToolNative)
  676. elif kitExtension == "sf2":
  677. plugins = checkFileSF2(kit, self.fToolNative)
  678. elif kitExtension == "sfz":
  679. plugins = checkFileSFZ(kit, self.fToolNative)
  680. else:
  681. plugins = None
  682. if plugins:
  683. self.fKitPlugins.append(plugins)
  684. self.fSomethingChanged = True
  685. if not self.fContinueChecking: break
  686. self.fLastCheckValue += self.fCurPercentValue
  687. def _pluginLook(self, percent, plugin):
  688. self.pluginLook.emit(percent, plugin)
  689. # ------------------------------------------------------------------------------------------------------------
  690. # Plugin Refresh Dialog
  691. class PluginRefreshW(QDialog):
  692. def __init__(self, parent):
  693. QDialog.__init__(self, parent)
  694. self.ui = ui_carla_refresh.Ui_PluginRefreshW()
  695. self.ui.setupUi(self)
  696. # -------------------------------------------------------------
  697. # Internal stuff
  698. self.fThread = SearchPluginsThread(self)
  699. # -------------------------------------------------------------
  700. # Load settings
  701. self.loadSettings()
  702. # -------------------------------------------------------------
  703. # Set-up GUI
  704. self.fIconYes = getIcon("dialog-ok-apply").pixmap(16, 16)
  705. self.fIconNo = getIcon("dialog-error").pixmap(16, 16)
  706. self.ui.b_skip.setVisible(False)
  707. if HAIKU:
  708. self.ui.ch_posix32.setText("Haiku 32bit")
  709. self.ui.ch_posix64.setText("Haiku 64bit")
  710. elif LINUX:
  711. self.ui.ch_posix32.setText("Linux 32bit")
  712. self.ui.ch_posix64.setText("Linux 64bit")
  713. elif MACOS:
  714. self.ui.ch_posix32.setText("MacOS 32bit")
  715. self.ui.ch_posix64.setText("MacOS 64bit")
  716. if gCarla.discovery_posix32 and not WINDOWS:
  717. self.ui.ico_posix32.setPixmap(self.fIconYes)
  718. else:
  719. self.ui.ico_posix32.setPixmap(self.fIconNo)
  720. self.ui.ch_posix32.setChecked(False)
  721. self.ui.ch_posix32.setEnabled(False)
  722. if gCarla.discovery_posix64 and not WINDOWS:
  723. self.ui.ico_posix64.setPixmap(self.fIconYes)
  724. else:
  725. self.ui.ico_posix64.setPixmap(self.fIconNo)
  726. self.ui.ch_posix64.setChecked(False)
  727. self.ui.ch_posix64.setEnabled(False)
  728. if gCarla.discovery_win32:
  729. self.ui.ico_win32.setPixmap(self.fIconYes)
  730. else:
  731. self.ui.ico_win32.setPixmap(self.fIconNo)
  732. self.ui.ch_win32.setChecked(False)
  733. self.ui.ch_win32.setEnabled(False)
  734. if gCarla.discovery_win64:
  735. self.ui.ico_win64.setPixmap(self.fIconYes)
  736. else:
  737. self.ui.ico_win64.setPixmap(self.fIconNo)
  738. self.ui.ch_win64.setChecked(False)
  739. self.ui.ch_win64.setEnabled(False)
  740. if haveLRDF:
  741. self.ui.ico_rdflib.setPixmap(self.fIconYes)
  742. else:
  743. self.ui.ico_rdflib.setPixmap(self.fIconNo)
  744. hasNative = bool(gCarla.discovery_native)
  745. hasNonNative = False
  746. if WINDOWS:
  747. if kIs64bit:
  748. hasNative = bool(gCarla.discovery_win64)
  749. hasNonNative = bool(gCarla.discovery_win32)
  750. self.fThread.setSearchToolNative(gCarla.discovery_win64)
  751. self.ui.ch_win64.setChecked(False)
  752. self.ui.ch_win64.setVisible(False)
  753. self.ui.ico_win64.setVisible(False)
  754. self.ui.label_win64.setVisible(False)
  755. else:
  756. hasNative = bool(gCarla.discovery_win32)
  757. hasNonNative = bool(gCarla.discovery_win64)
  758. self.fThread.setSearchToolNative(gCarla.discovery_win32)
  759. self.ui.ch_win32.setChecked(False)
  760. self.ui.ch_win32.setVisible(False)
  761. self.ui.ico_win32.setVisible(False)
  762. self.ui.label_win32.setVisible(False)
  763. elif LINUX or MACOS:
  764. if kIs64bit:
  765. hasNonNative = bool(gCarla.discovery_posix32 or gCarla.discovery_win32 or gCarla.discovery_win64)
  766. self.ui.ch_posix64.setChecked(False)
  767. self.ui.ch_posix64.setVisible(False)
  768. self.ui.ico_posix64.setVisible(False)
  769. self.ui.label_posix64.setVisible(False)
  770. else:
  771. hasNonNative = bool(gCarla.discovery_posix64 or gCarla.discovery_win32 or gCarla.discovery_win64)
  772. self.ui.ch_posix32.setChecked(False)
  773. self.ui.ch_posix32.setVisible(False)
  774. self.ui.ico_posix32.setVisible(False)
  775. self.ui.label_posix32.setVisible(False)
  776. if hasNative:
  777. self.ui.ico_native.setPixmap(self.fIconYes)
  778. else:
  779. self.ui.ico_native.setPixmap(self.fIconNo)
  780. self.ui.ch_native.setChecked(False)
  781. self.ui.ch_native.setEnabled(False)
  782. self.ui.ch_csound.setChecked(False)
  783. self.ui.ch_csound.setEnabled(False)
  784. self.ui.ch_gig.setChecked(False)
  785. self.ui.ch_gig.setEnabled(False)
  786. self.ui.ch_sf2.setChecked(False)
  787. self.ui.ch_sf2.setEnabled(False)
  788. self.ui.ch_sfz.setChecked(False)
  789. self.ui.ch_sfz.setEnabled(False)
  790. if not hasNonNative:
  791. self.ui.ch_ladspa.setChecked(False)
  792. self.ui.ch_ladspa.setEnabled(False)
  793. self.ui.ch_dssi.setChecked(False)
  794. self.ui.ch_dssi.setEnabled(False)
  795. self.ui.ch_lv2.setChecked(False)
  796. self.ui.ch_lv2.setEnabled(False)
  797. self.ui.ch_vst.setChecked(False)
  798. self.ui.ch_vst.setEnabled(False)
  799. self.ui.ch_au.setChecked(False)
  800. self.ui.ch_au.setEnabled(False)
  801. self.ui.b_start.setEnabled(False)
  802. if not MACOS:
  803. self.ui.ch_au.setChecked(False)
  804. self.ui.ch_au.setEnabled(False)
  805. self.ui.ch_au.setVisible(False)
  806. # -------------------------------------------------------------
  807. # Set-up connections
  808. self.ui.b_start.clicked.connect(self.slot_start)
  809. self.ui.b_skip.clicked.connect(self.slot_skip)
  810. self.ui.ch_native.clicked.connect(self.slot_checkTools)
  811. self.ui.ch_posix32.clicked.connect(self.slot_checkTools)
  812. self.ui.ch_posix64.clicked.connect(self.slot_checkTools)
  813. self.ui.ch_win32.clicked.connect(self.slot_checkTools)
  814. self.ui.ch_win64.clicked.connect(self.slot_checkTools)
  815. self.ui.ch_ladspa.clicked.connect(self.slot_checkTools)
  816. self.ui.ch_dssi.clicked.connect(self.slot_checkTools)
  817. self.ui.ch_lv2.clicked.connect(self.slot_checkTools)
  818. self.ui.ch_vst.clicked.connect(self.slot_checkTools)
  819. self.ui.ch_au.clicked.connect(self.slot_checkTools)
  820. self.ui.ch_csound.clicked.connect(self.slot_checkTools)
  821. self.ui.ch_gig.clicked.connect(self.slot_checkTools)
  822. self.ui.ch_sf2.clicked.connect(self.slot_checkTools)
  823. self.ui.ch_sfz.clicked.connect(self.slot_checkTools)
  824. self.fThread.pluginLook.connect(self.slot_handlePluginLook)
  825. self.fThread.finished.connect(self.slot_handlePluginThreadFinished)
  826. @pyqtSlot()
  827. def slot_start(self):
  828. self.ui.progressBar.setMinimum(0)
  829. self.ui.progressBar.setMaximum(100)
  830. self.ui.progressBar.setValue(0)
  831. self.ui.b_start.setEnabled(False)
  832. self.ui.b_skip.setVisible(True)
  833. self.ui.b_close.setVisible(False)
  834. native, posix32, posix64, win32, win64 = (self.ui.ch_native.isChecked(),
  835. self.ui.ch_posix32.isChecked(), self.ui.ch_posix64.isChecked(),
  836. self.ui.ch_win32.isChecked(), self.ui.ch_win64.isChecked())
  837. ladspa, dssi, lv2, vst, au, csound, gig, sf2, sfz = (self.ui.ch_ladspa.isChecked(), self.ui.ch_dssi.isChecked(),
  838. self.ui.ch_lv2.isChecked(), self.ui.ch_vst.isChecked(),
  839. self.ui.ch_au.isChecked(), self.ui.ch_csound.isChecked(),
  840. self.ui.ch_gig.isChecked(), self.ui.ch_sf2.isChecked(), self.ui.ch_sfz.isChecked())
  841. self.fThread.setSearchBinaryTypes(native, posix32, posix64, win32, win64)
  842. self.fThread.setSearchPluginTypes(ladspa, dssi, lv2, vst, au, csound, gig, sf2, sfz)
  843. self.fThread.start()
  844. @pyqtSlot()
  845. def slot_skip(self):
  846. killDiscovery()
  847. @pyqtSlot()
  848. def slot_checkTools(self):
  849. enabled1 = bool(self.ui.ch_native.isChecked() or self.ui.ch_posix32.isChecked() or self.ui.ch_posix64.isChecked() or self.ui.ch_win32.isChecked() or self.ui.ch_win64.isChecked())
  850. enabled2 = bool(self.ui.ch_ladspa.isChecked() or self.ui.ch_dssi.isChecked() or self.ui.ch_lv2.isChecked() or self.ui.ch_vst.isChecked() or self.ui.ch_au.isChecked() or
  851. self.ui.ch_csound.isChecked() or self.ui.ch_gig.isChecked() or self.ui.ch_sf2.isChecked() or self.ui.ch_sfz.isChecked())
  852. self.ui.b_start.setEnabled(enabled1 and enabled2)
  853. @pyqtSlot(int, str)
  854. def slot_handlePluginLook(self, percent, plugin):
  855. self.ui.progressBar.setFormat("%s" % plugin)
  856. self.ui.progressBar.setValue(percent)
  857. @pyqtSlot()
  858. def slot_handlePluginThreadFinished(self):
  859. self.ui.progressBar.setMinimum(0)
  860. self.ui.progressBar.setMaximum(1)
  861. self.ui.progressBar.setValue(1)
  862. self.ui.progressBar.setFormat(self.tr("Done"))
  863. self.ui.b_start.setEnabled(True)
  864. self.ui.b_skip.setVisible(False)
  865. self.ui.b_close.setVisible(True)
  866. def loadSettings(self):
  867. settings = QSettings()
  868. self.ui.ch_ladspa.setChecked(settings.value("PluginDatabase/SearchLADSPA", True, type=bool))
  869. self.ui.ch_dssi.setChecked(settings.value("PluginDatabase/SearchDSSI", True, type=bool))
  870. self.ui.ch_lv2.setChecked(settings.value("PluginDatabase/SearchLV2", True, type=bool))
  871. self.ui.ch_vst.setChecked(settings.value("PluginDatabase/SearchVST", True, type=bool))
  872. self.ui.ch_au.setChecked(settings.value("PluginDatabase/SearchAU", True, type=bool))
  873. self.ui.ch_csound.setChecked(settings.value("PluginDatabase/SearchCsound", False, type=bool))
  874. self.ui.ch_gig.setChecked(settings.value("PluginDatabase/SearchGIG", False, type=bool))
  875. self.ui.ch_sf2.setChecked(settings.value("PluginDatabase/SearchSF2", False, type=bool))
  876. self.ui.ch_sfz.setChecked(settings.value("PluginDatabase/SearchSFZ", False, type=bool))
  877. self.ui.ch_native.setChecked(settings.value("PluginDatabase/SearchNative", True, type=bool))
  878. self.ui.ch_posix32.setChecked(settings.value("PluginDatabase/SearchPOSIX32", False, type=bool))
  879. self.ui.ch_posix64.setChecked(settings.value("PluginDatabase/SearchPOSIX64", False, type=bool))
  880. self.ui.ch_win32.setChecked(settings.value("PluginDatabase/SearchWin32", False, type=bool))
  881. self.ui.ch_win64.setChecked(settings.value("PluginDatabase/SearchWin64", False, type=bool))
  882. def saveSettings(self):
  883. settings = QSettings()
  884. settings.setValue("PluginDatabase/SearchLADSPA", self.ui.ch_ladspa.isChecked())
  885. settings.setValue("PluginDatabase/SearchDSSI", self.ui.ch_dssi.isChecked())
  886. settings.setValue("PluginDatabase/SearchLV2", self.ui.ch_lv2.isChecked())
  887. settings.setValue("PluginDatabase/SearchVST", self.ui.ch_vst.isChecked())
  888. settings.setValue("PluginDatabase/SearchAU", self.ui.ch_au.isChecked())
  889. settings.setValue("PluginDatabase/SearchCsound", self.ui.ch_csound.isChecked())
  890. settings.setValue("PluginDatabase/SearchGIG", self.ui.ch_gig.isChecked())
  891. settings.setValue("PluginDatabase/SearchSF2", self.ui.ch_sf2.isChecked())
  892. settings.setValue("PluginDatabase/SearchSFZ", self.ui.ch_sfz.isChecked())
  893. settings.setValue("PluginDatabase/SearchNative", self.ui.ch_native.isChecked())
  894. settings.setValue("PluginDatabase/SearchPOSIX32", self.ui.ch_posix32.isChecked())
  895. settings.setValue("PluginDatabase/SearchPOSIX64", self.ui.ch_posix64.isChecked())
  896. settings.setValue("PluginDatabase/SearchWin32", self.ui.ch_win32.isChecked())
  897. settings.setValue("PluginDatabase/SearchWin64", self.ui.ch_win64.isChecked())
  898. def closeEvent(self, event):
  899. self.saveSettings()
  900. if self.fThread.isRunning():
  901. self.fThread.stop()
  902. killDiscovery()
  903. #self.fThread.terminate()
  904. self.fThread.wait()
  905. if self.fThread.hasSomethingChanged():
  906. self.accept()
  907. else:
  908. self.reject()
  909. QDialog.closeEvent(self, event)
  910. def done(self, r):
  911. QDialog.done(self, r)
  912. self.close()
  913. # ------------------------------------------------------------------------------------------------------------
  914. # Plugin Database Dialog
  915. class PluginDatabaseW(QDialog):
  916. def __init__(self, parent):
  917. QDialog.__init__(self, parent)
  918. self.ui = ui_carla_database.Ui_PluginDatabaseW()
  919. self.ui.setupUi(self)
  920. # -------------------------------------------------------------
  921. # Internal stuff
  922. self.fLastTableIndex = 0
  923. self.fRetPlugin = None
  924. self.fRealParent = parent
  925. # -------------------------------------------------------------
  926. # Load settings
  927. self.loadSettings()
  928. # -------------------------------------------------------------
  929. # Set-up GUI
  930. self.ui.b_add.setEnabled(False)
  931. if BINARY_NATIVE in (BINARY_POSIX32, BINARY_WIN32):
  932. self.ui.ch_bridged.setText(self.tr("Bridged (64bit)"))
  933. else:
  934. self.ui.ch_bridged.setText(self.tr("Bridged (32bit)"))
  935. if not (LINUX or MACOS):
  936. self.ui.ch_bridged_wine.setChecked(False)
  937. self.ui.ch_bridged_wine.setEnabled(False)
  938. # -------------------------------------------------------------
  939. # Set-up connections
  940. self.ui.b_add.clicked.connect(self.slot_addPlugin)
  941. self.ui.b_refresh.clicked.connect(self.slot_refreshPlugins)
  942. self.ui.tb_filters.clicked.connect(self.slot_maybeShowFilters)
  943. self.ui.lineEdit.textChanged.connect(self.slot_checkFilters)
  944. self.ui.tableWidget.currentCellChanged.connect(self.slot_checkPlugin)
  945. self.ui.tableWidget.cellDoubleClicked.connect(self.slot_addPlugin)
  946. self.ui.ch_effects.clicked.connect(self.slot_checkFilters)
  947. self.ui.ch_instruments.clicked.connect(self.slot_checkFilters)
  948. self.ui.ch_midi.clicked.connect(self.slot_checkFilters)
  949. self.ui.ch_other.clicked.connect(self.slot_checkFilters)
  950. self.ui.ch_internal.clicked.connect(self.slot_checkFilters)
  951. self.ui.ch_ladspa.clicked.connect(self.slot_checkFilters)
  952. self.ui.ch_dssi.clicked.connect(self.slot_checkFilters)
  953. self.ui.ch_lv2.clicked.connect(self.slot_checkFilters)
  954. self.ui.ch_vst.clicked.connect(self.slot_checkFilters)
  955. self.ui.ch_au.clicked.connect(self.slot_checkFilters)
  956. self.ui.ch_csound.clicked.connect(self.slot_checkFilters)
  957. self.ui.ch_kits.clicked.connect(self.slot_checkFilters)
  958. self.ui.ch_native.clicked.connect(self.slot_checkFilters)
  959. self.ui.ch_bridged.clicked.connect(self.slot_checkFilters)
  960. self.ui.ch_bridged_wine.clicked.connect(self.slot_checkFilters)
  961. self.ui.ch_rtsafe.clicked.connect(self.slot_checkFilters)
  962. self.ui.ch_gui.clicked.connect(self.slot_checkFilters)
  963. self.ui.ch_stereo.clicked.connect(self.slot_checkFilters)
  964. # -------------------------------------------------------------
  965. @pyqtSlot()
  966. def slot_addPlugin(self):
  967. if self.ui.tableWidget.currentRow() >= 0:
  968. self.fRetPlugin = self.ui.tableWidget.item(self.ui.tableWidget.currentRow(), 0).data(Qt.UserRole)
  969. self.accept()
  970. else:
  971. self.reject()
  972. @pyqtSlot(int)
  973. def slot_checkPlugin(self, row):
  974. self.ui.b_add.setEnabled(row >= 0)
  975. @pyqtSlot()
  976. def slot_checkFilters(self):
  977. self._checkFilters()
  978. @pyqtSlot()
  979. def slot_maybeShowFilters(self):
  980. self._showFilters(not self.ui.frame.isVisible())
  981. @pyqtSlot()
  982. def slot_refreshPlugins(self):
  983. if PluginRefreshW(self).exec_():
  984. self._reAddPlugins()
  985. if self.fRealParent:
  986. self.fRealParent.setLoadRDFsNeeded()
  987. def _checkFilters(self):
  988. text = self.ui.lineEdit.text().lower()
  989. hideEffects = not self.ui.ch_effects.isChecked()
  990. hideInstruments = not self.ui.ch_instruments.isChecked()
  991. hideMidi = not self.ui.ch_midi.isChecked()
  992. hideOther = not self.ui.ch_other.isChecked()
  993. hideInternal = not self.ui.ch_internal.isChecked()
  994. hideLadspa = not self.ui.ch_ladspa.isChecked()
  995. hideDssi = not self.ui.ch_dssi.isChecked()
  996. hideLV2 = not self.ui.ch_lv2.isChecked()
  997. hideVST = not self.ui.ch_vst.isChecked()
  998. hideAU = not self.ui.ch_au.isChecked()
  999. hideCsound = not self.ui.ch_csound.isChecked()
  1000. hideKits = not self.ui.ch_kits.isChecked()
  1001. hideNative = not self.ui.ch_native.isChecked()
  1002. hideBridged = not self.ui.ch_bridged.isChecked()
  1003. hideBridgedWine = not self.ui.ch_bridged_wine.isChecked()
  1004. hideNonRtSafe = self.ui.ch_rtsafe.isChecked()
  1005. hideNonGui = self.ui.ch_gui.isChecked()
  1006. hideNonStereo = self.ui.ch_stereo.isChecked()
  1007. if HAIKU or LINUX or MACOS:
  1008. nativeBins = [BINARY_POSIX32, BINARY_POSIX64]
  1009. wineBins = [BINARY_WIN32, BINARY_WIN64]
  1010. elif WINDOWS:
  1011. nativeBins = [BINARY_WIN32, BINARY_WIN64]
  1012. wineBins = []
  1013. else:
  1014. nativeBins = []
  1015. wineBins = []
  1016. rowCount = self.ui.tableWidget.rowCount()
  1017. for i in range(rowCount):
  1018. self.ui.tableWidget.showRow(i)
  1019. plugin = self.ui.tableWidget.item(i, 0).data(Qt.UserRole)
  1020. aIns = plugin['audio.ins']
  1021. aOuts = plugin['audio.outs']
  1022. mIns = plugin['midi.ins']
  1023. mOuts = plugin['midi.outs']
  1024. ptype = self.ui.tableWidget.item(i, 12).text()
  1025. isSynth = bool(plugin['hints'] & PLUGIN_IS_SYNTH)
  1026. isEffect = bool(aIns > 0 < aOuts and not isSynth)
  1027. isMidi = bool(aIns == 0 and aOuts == 0 and mIns > 0 < mOuts)
  1028. isKit = bool(ptype in ("GIG", "SF2", "SFZ"))
  1029. isOther = bool(not (isEffect or isSynth or isMidi or isKit))
  1030. isNative = bool(plugin['build'] == BINARY_NATIVE)
  1031. isRtSafe = bool(plugin['hints'] & PLUGIN_IS_RTSAFE)
  1032. isStereo = bool(aIns == 2 and aOuts == 2) or (isSynth and aOuts == 2)
  1033. hasGui = bool(plugin['hints'] & PLUGIN_HAS_CUSTOM_UI)
  1034. isBridged = bool(not isNative and plugin['build'] in nativeBins)
  1035. isBridgedWine = bool(not isNative and plugin['build'] in wineBins)
  1036. if hideEffects and isEffect:
  1037. self.ui.tableWidget.hideRow(i)
  1038. elif hideInstruments and isSynth:
  1039. self.ui.tableWidget.hideRow(i)
  1040. elif hideMidi and isMidi:
  1041. self.ui.tableWidget.hideRow(i)
  1042. elif hideOther and isOther:
  1043. self.ui.tableWidget.hideRow(i)
  1044. elif hideKits and isKit:
  1045. self.ui.tableWidget.hideRow(i)
  1046. elif hideInternal and ptype == self.tr("Internal"):
  1047. self.ui.tableWidget.hideRow(i)
  1048. elif hideLadspa and ptype == "LADSPA":
  1049. self.ui.tableWidget.hideRow(i)
  1050. elif hideDssi and ptype == "DSSI":
  1051. self.ui.tableWidget.hideRow(i)
  1052. elif hideLV2 and ptype == "LV2":
  1053. self.ui.tableWidget.hideRow(i)
  1054. elif hideVST and ptype == "VST":
  1055. self.ui.tableWidget.hideRow(i)
  1056. elif hideAU and ptype == "AU":
  1057. self.ui.tableWidget.hideRow(i)
  1058. elif hideCsound and ptype == "CSD":
  1059. self.ui.tableWidget.hideRow(i)
  1060. elif hideNative and isNative:
  1061. self.ui.tableWidget.hideRow(i)
  1062. elif hideBridged and isBridged:
  1063. self.ui.tableWidget.hideRow(i)
  1064. elif hideBridgedWine and isBridgedWine:
  1065. self.ui.tableWidget.hideRow(i)
  1066. elif hideNonRtSafe and not isRtSafe:
  1067. self.ui.tableWidget.hideRow(i)
  1068. elif hideNonGui and not hasGui:
  1069. self.ui.tableWidget.hideRow(i)
  1070. elif hideNonStereo and not isStereo:
  1071. self.ui.tableWidget.hideRow(i)
  1072. elif (text and not (
  1073. text in self.ui.tableWidget.item(i, 0).text().lower() or
  1074. text in self.ui.tableWidget.item(i, 1).text().lower() or
  1075. text in self.ui.tableWidget.item(i, 2).text().lower() or
  1076. text in self.ui.tableWidget.item(i, 3).text().lower() or
  1077. text in self.ui.tableWidget.item(i, 13).text().lower())):
  1078. self.ui.tableWidget.hideRow(i)
  1079. def _showFilters(self, yesNo):
  1080. self.ui.tb_filters.setArrowType(Qt.UpArrow if yesNo else Qt.DownArrow)
  1081. self.ui.frame.setVisible(yesNo)
  1082. def _addPluginToTable(self, plugin, ptype):
  1083. if plugin['API'] != PLUGIN_QUERY_API_VERSION:
  1084. return
  1085. index = self.fLastTableIndex
  1086. if plugin['build'] == BINARY_NATIVE:
  1087. bridgeText = self.tr("No")
  1088. else:
  1089. if LINUX or MACOS:
  1090. if plugin['build'] == BINARY_WIN32:
  1091. typeText = "32bit"
  1092. elif plugin['build'] == BINARY_WIN64:
  1093. typeText = "64bit"
  1094. else:
  1095. typeText = self.tr("Unknown")
  1096. else:
  1097. if plugin['build'] == BINARY_POSIX32:
  1098. typeText = "32bit"
  1099. elif plugin['build'] == BINARY_POSIX64:
  1100. typeText = "64bit"
  1101. elif plugin['build'] == BINARY_WIN32:
  1102. typeText = "Windows 32bit"
  1103. elif plugin['build'] == BINARY_WIN64:
  1104. typeText = "Windows 64bit"
  1105. else:
  1106. typeText = self.tr("Unknown")
  1107. bridgeText = self.tr("Yes (%s)" % typeText)
  1108. self.ui.tableWidget.insertRow(index)
  1109. self.ui.tableWidget.setItem(index, 0, QTableWidgetItem(str(plugin['name'])))
  1110. self.ui.tableWidget.setItem(index, 1, QTableWidgetItem(str(plugin['label'])))
  1111. self.ui.tableWidget.setItem(index, 2, QTableWidgetItem(str(plugin['maker'])))
  1112. self.ui.tableWidget.setItem(index, 3, QTableWidgetItem(str(plugin['uniqueId'])))
  1113. self.ui.tableWidget.setItem(index, 4, QTableWidgetItem(str(plugin['audio.ins'])))
  1114. self.ui.tableWidget.setItem(index, 5, QTableWidgetItem(str(plugin['audio.outs'])))
  1115. self.ui.tableWidget.setItem(index, 6, QTableWidgetItem(str(plugin['parameters.ins'])))
  1116. self.ui.tableWidget.setItem(index, 7, QTableWidgetItem(str(plugin['parameters.outs'])))
  1117. self.ui.tableWidget.setItem(index, 8, QTableWidgetItem(str(plugin['programs.total'])))
  1118. self.ui.tableWidget.setItem(index, 9, QTableWidgetItem(self.tr("Yes") if (plugin['hints'] & PLUGIN_HAS_CUSTOM_UI) else self.tr("No")))
  1119. self.ui.tableWidget.setItem(index, 10, QTableWidgetItem(self.tr("Yes") if (plugin['hints'] & PLUGIN_IS_SYNTH) else self.tr("No")))
  1120. self.ui.tableWidget.setItem(index, 11, QTableWidgetItem(bridgeText))
  1121. self.ui.tableWidget.setItem(index, 12, QTableWidgetItem(ptype))
  1122. self.ui.tableWidget.setItem(index, 13, QTableWidgetItem(str(plugin['filename'])))
  1123. self.ui.tableWidget.item(index, 0).setData(Qt.UserRole, plugin)
  1124. self.fLastTableIndex += 1
  1125. def _reAddPlugins(self):
  1126. settingsDB = QSettings("falkTX", "CarlaPlugins2")
  1127. for x in range(self.ui.tableWidget.rowCount()):
  1128. self.ui.tableWidget.removeRow(0)
  1129. self.fLastTableIndex = 0
  1130. self.ui.tableWidget.setSortingEnabled(False)
  1131. internalCount = 0
  1132. ladspaCount = 0
  1133. dssiCount = 0
  1134. lv2Count = 0
  1135. vstCount = 0
  1136. auCount = 0
  1137. csdCount = 0
  1138. kitCount = 0
  1139. # ---------------------------------------------------------------------------
  1140. # Internal
  1141. internalPlugins = toList(settingsDB.value("Plugins/Internal", []))
  1142. for plugins in internalPlugins:
  1143. internalCount += len(plugins)
  1144. canRefreshInternals = not (gCarla.isControl or gCarla.isPlugin or gCarla.host is None)
  1145. if canRefreshInternals and internalCount != gCarla.host.get_internal_plugin_count():
  1146. internalCount = gCarla.host.get_internal_plugin_count()
  1147. internalPlugins = []
  1148. for i in range(gCarla.host.get_internal_plugin_count()):
  1149. descInfo = gCarla.host.get_internal_plugin_info(i)
  1150. plugins = checkPluginInternal(descInfo)
  1151. if plugins:
  1152. internalPlugins.append(plugins)
  1153. settingsDB.setValue("Plugins/Internal", internalPlugins)
  1154. for plugins in internalPlugins:
  1155. for plugin in plugins:
  1156. self._addPluginToTable(plugin, self.tr("Internal"))
  1157. del internalPlugins
  1158. # ---------------------------------------------------------------------------
  1159. # LADSPA
  1160. ladspaPlugins = []
  1161. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_native", []))
  1162. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_posix32", []))
  1163. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_posix64", []))
  1164. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_win32", []))
  1165. ladspaPlugins += toList(settingsDB.value("Plugins/LADSPA_win64", []))
  1166. for plugins in ladspaPlugins:
  1167. for plugin in plugins:
  1168. self._addPluginToTable(plugin, "LADSPA")
  1169. ladspaCount += 1
  1170. del ladspaPlugins
  1171. # ---------------------------------------------------------------------------
  1172. # DSSI
  1173. dssiPlugins = []
  1174. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_native", []))
  1175. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_posix32", []))
  1176. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_posix64", []))
  1177. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_win32", []))
  1178. dssiPlugins += toList(settingsDB.value("Plugins/DSSI_win64", []))
  1179. for plugins in dssiPlugins:
  1180. for plugin in plugins:
  1181. self._addPluginToTable(plugin, "DSSI")
  1182. dssiCount += 1
  1183. del dssiPlugins
  1184. # ---------------------------------------------------------------------------
  1185. # LV2
  1186. lv2Plugins = []
  1187. lv2Plugins += toList(settingsDB.value("Plugins/LV2_native", []))
  1188. lv2Plugins += toList(settingsDB.value("Plugins/LV2_posix32", []))
  1189. lv2Plugins += toList(settingsDB.value("Plugins/LV2_posix64", []))
  1190. lv2Plugins += toList(settingsDB.value("Plugins/LV2_win32", []))
  1191. lv2Plugins += toList(settingsDB.value("Plugins/LV2_win64", []))
  1192. for plugins in lv2Plugins:
  1193. for plugin in plugins:
  1194. self._addPluginToTable(plugin, "LV2")
  1195. lv2Count += 1
  1196. del lv2Plugins
  1197. # ---------------------------------------------------------------------------
  1198. # VST
  1199. vstPlugins = []
  1200. vstPlugins += toList(settingsDB.value("Plugins/VST_native", []))
  1201. vstPlugins += toList(settingsDB.value("Plugins/VST_posix32", []))
  1202. vstPlugins += toList(settingsDB.value("Plugins/VST_posix64", []))
  1203. vstPlugins += toList(settingsDB.value("Plugins/VST_win32", []))
  1204. vstPlugins += toList(settingsDB.value("Plugins/VST_win64", []))
  1205. for plugins in vstPlugins:
  1206. for plugin in plugins:
  1207. self._addPluginToTable(plugin, "VST")
  1208. vstCount += 1
  1209. del vstPlugins
  1210. # ---------------------------------------------------------------------------
  1211. # AU
  1212. if MACOS:
  1213. auPlugins = []
  1214. auPlugins += toList(settingsDB.value("Plugins/AU_native", []))
  1215. auPlugins += toList(settingsDB.value("Plugins/AU_posix32", []))
  1216. auPlugins += toList(settingsDB.value("Plugins/AU_posix64", []))
  1217. for plugins in auPlugins:
  1218. for plugin in plugins:
  1219. self._addPluginToTable(plugin, "AU")
  1220. auCount += 1
  1221. del auPlugins
  1222. # ---------------------------------------------------------------------------
  1223. # Csound
  1224. csds = toList(settingsDB.value("Plugins/CSD", []))
  1225. for csd in csds:
  1226. for csd_i in csd:
  1227. self._addPluginToTable(csd_i, "CSD")
  1228. csdCount += 1
  1229. del csds
  1230. # ---------------------------------------------------------------------------
  1231. # Kits
  1232. gigs = toList(settingsDB.value("Plugins/GIG", []))
  1233. for gig in gigs:
  1234. for gig_i in gig:
  1235. self._addPluginToTable(gig_i, "GIG")
  1236. kitCount += 1
  1237. del gigs
  1238. # ---------------------------------------------------------------------------
  1239. sf2s = toList(settingsDB.value("Plugins/SF2", []))
  1240. for sf2 in sf2s:
  1241. for sf2_i in sf2:
  1242. self._addPluginToTable(sf2_i, "SF2")
  1243. kitCount += 1
  1244. del sf2s
  1245. # ---------------------------------------------------------------------------
  1246. sfzs = toList(settingsDB.value("Plugins/SFZ", []))
  1247. for sfz in sfzs:
  1248. for sfz_i in sfz:
  1249. self._addPluginToTable(sfz_i, "SFZ")
  1250. kitCount += 1
  1251. del sfzs
  1252. # ---------------------------------------------------------------------------
  1253. self.ui.tableWidget.setSortingEnabled(True)
  1254. self.ui.tableWidget.sortByColumn(0, Qt.AscendingOrder)
  1255. if MACOS:
  1256. self.ui.label.setText(self.tr("Have %i Internal, %i LADSPA, %i DSSI, %i LV2, %i VST and %i AudioUnit plugins, plus %i CSound modules and %i Sound Kits" % (
  1257. internalCount, ladspaCount, dssiCount, lv2Count, vstCount, auCount, csdCount, kitCount)))
  1258. else:
  1259. self.ui.label.setText(self.tr("Have %i Internal, %i LADSPA, %i DSSI, %i LV2 and %i VST plugins, plus %i CSound modules and %i Sound Kits" % (
  1260. internalCount, ladspaCount, dssiCount, lv2Count, vstCount, csdCount, kitCount)))
  1261. self._checkFilters()
  1262. def loadSettings(self):
  1263. settings = QSettings()
  1264. self.restoreGeometry(settings.value("PluginDatabase/Geometry", ""))
  1265. self.ui.tableWidget.horizontalHeader().restoreState(settings.value("PluginDatabase/TableGeometry", ""))
  1266. self.ui.ch_effects.setChecked(settings.value("PluginDatabase/ShowEffects", True, type=bool))
  1267. self.ui.ch_instruments.setChecked(settings.value("PluginDatabase/ShowInstruments", True, type=bool))
  1268. self.ui.ch_midi.setChecked(settings.value("PluginDatabase/ShowMIDI", True, type=bool))
  1269. self.ui.ch_other.setChecked(settings.value("PluginDatabase/ShowOther", True, type=bool))
  1270. self.ui.ch_internal.setChecked(settings.value("PluginDatabase/ShowInternal", True, type=bool))
  1271. self.ui.ch_ladspa.setChecked(settings.value("PluginDatabase/ShowLADSPA", True, type=bool))
  1272. self.ui.ch_dssi.setChecked(settings.value("PluginDatabase/ShowDSSI", True, type=bool))
  1273. self.ui.ch_lv2.setChecked(settings.value("PluginDatabase/ShowLV2", True, type=bool))
  1274. self.ui.ch_vst.setChecked(settings.value("PluginDatabase/ShowVST", True, type=bool))
  1275. self.ui.ch_au.setChecked(settings.value("PluginDatabase/ShowAU", True, type=bool))
  1276. self.ui.ch_csound.setChecked(settings.value("PluginDatabase/ShowCsound", True, type=bool))
  1277. self.ui.ch_kits.setChecked(settings.value("PluginDatabase/ShowKits", True, type=bool))
  1278. self.ui.ch_native.setChecked(settings.value("PluginDatabase/ShowNative", True, type=bool))
  1279. self.ui.ch_bridged.setChecked(settings.value("PluginDatabase/ShowBridged", True, type=bool))
  1280. self.ui.ch_bridged_wine.setChecked(settings.value("PluginDatabase/ShowBridgedWine", True, type=bool))
  1281. self.ui.ch_rtsafe.setChecked(settings.value("PluginDatabase/ShowRtSafe", False, type=bool))
  1282. self.ui.ch_gui.setChecked(settings.value("PluginDatabase/ShowHasGUI", False, type=bool))
  1283. self.ui.ch_stereo.setChecked(settings.value("PluginDatabase/ShowStereoOnly", False, type=bool))
  1284. self._showFilters(settings.value("PluginDatabase/ShowFilters", False, type=bool))
  1285. self._reAddPlugins()
  1286. def saveSettings(self):
  1287. settings = QSettings()
  1288. settings.setValue("PluginDatabase/Geometry", self.saveGeometry())
  1289. settings.setValue("PluginDatabase/TableGeometry", self.ui.tableWidget.horizontalHeader().saveState())
  1290. settings.setValue("PluginDatabase/ShowFilters", (self.ui.tb_filters.arrowType() == Qt.UpArrow))
  1291. settings.setValue("PluginDatabase/ShowEffects", self.ui.ch_effects.isChecked())
  1292. settings.setValue("PluginDatabase/ShowInstruments", self.ui.ch_instruments.isChecked())
  1293. settings.setValue("PluginDatabase/ShowMIDI", self.ui.ch_midi.isChecked())
  1294. settings.setValue("PluginDatabase/ShowOther", self.ui.ch_other.isChecked())
  1295. settings.setValue("PluginDatabase/ShowInternal", self.ui.ch_internal.isChecked())
  1296. settings.setValue("PluginDatabase/ShowLADSPA", self.ui.ch_ladspa.isChecked())
  1297. settings.setValue("PluginDatabase/ShowDSSI", self.ui.ch_dssi.isChecked())
  1298. settings.setValue("PluginDatabase/ShowLV2", self.ui.ch_lv2.isChecked())
  1299. settings.setValue("PluginDatabase/ShowVST", self.ui.ch_vst.isChecked())
  1300. settings.setValue("PluginDatabase/ShowAU", self.ui.ch_au.isChecked())
  1301. settings.setValue("PluginDatabase/ShowCsound", self.ui.ch_csound.isChecked())
  1302. settings.setValue("PluginDatabase/ShowKits", self.ui.ch_kits.isChecked())
  1303. settings.setValue("PluginDatabase/ShowNative", self.ui.ch_native.isChecked())
  1304. settings.setValue("PluginDatabase/ShowBridged", self.ui.ch_bridged.isChecked())
  1305. settings.setValue("PluginDatabase/ShowBridgedWine", self.ui.ch_bridged_wine.isChecked())
  1306. settings.setValue("PluginDatabase/ShowRtSafe", self.ui.ch_rtsafe.isChecked())
  1307. settings.setValue("PluginDatabase/ShowHasGUI", self.ui.ch_gui.isChecked())
  1308. settings.setValue("PluginDatabase/ShowStereoOnly", self.ui.ch_stereo.isChecked())
  1309. def closeEvent(self, event):
  1310. self.saveSettings()
  1311. QDialog.closeEvent(self, event)
  1312. def done(self, r):
  1313. QDialog.done(self, r)
  1314. self.close()
  1315. # ------------------------------------------------------------------------------------------------------------
  1316. # Main
  1317. if __name__ == '__main__':
  1318. from carla_style import CarlaApplication
  1319. app = CarlaApplication()
  1320. initHost("Settings", None, False)
  1321. gui = PluginDatabaseW(None)
  1322. gui.show()
  1323. sys.exit(app.exec_())