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.

carla_database.py 72KB

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