Collection of tools useful for audio production
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.

2057 lines
87KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla Backend code
  4. # Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com>
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # 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 COPYING file
  17. # Imports (Global)
  18. import json
  19. from PyQt4.QtCore import QThread
  20. from PyQt4.QtGui import QApplication, QMainWindow, QTableWidgetItem
  21. # Imports (Custom Stuff)
  22. import ui_carla, ui_carla_about, ui_carla_database, ui_carla_refresh
  23. from carla_backend import *
  24. from shared_settings import *
  25. # set defaults
  26. DEFAULT_PROJECT_FOLDER = HOME
  27. setDefaultProjectFolder(DEFAULT_PROJECT_FOLDER)
  28. setDefaultPluginsPaths(LADSPA_PATH, DSSI_PATH, LV2_PATH, VST_PATH, GIG_PATH, SF2_PATH, SFZ_PATH)
  29. # Separate Thread for Plugin Search
  30. class SearchPluginsThread(QThread):
  31. def __init__(self, parent):
  32. QThread.__init__(self, parent)
  33. self.settings_db = self.parent().settings_db
  34. self.check_native = False
  35. self.check_posix32 = False
  36. self.check_posix64 = False
  37. self.check_win32 = False
  38. self.check_win64 = False
  39. self.check_ladspa = False
  40. self.check_dssi = False
  41. self.check_lv2 = False
  42. self.check_vst = False
  43. self.check_gig = False
  44. self.check_sf2 = False
  45. self.check_sfz = False
  46. self.tool_native = carla_discovery_native
  47. def skipPlugin(self):
  48. # TODO - windows and mac support
  49. apps = ""
  50. apps += " carla-discovery"
  51. apps += " carla-discovery-native"
  52. apps += " carla-discovery-posix32"
  53. apps += " carla-discovery-posix64"
  54. apps += " carla-discovery-win32.exe"
  55. apps += " carla-discovery-win64.exe"
  56. if LINUX:
  57. os.system("killall -KILL %s" % apps)
  58. def pluginLook(self, percent, plugin):
  59. self.emit(SIGNAL("PluginLook(int, QString)"), percent, plugin)
  60. def setSearchBinaryTypes(self, native, posix32, posix64, win32, win64):
  61. self.check_native = native
  62. self.check_posix32 = posix32
  63. self.check_posix64 = posix64
  64. self.check_win32 = win32
  65. self.check_win64 = win64
  66. def setSearchPluginTypes(self, ladspa, dssi, lv2, vst, gig, sf2, sfz):
  67. self.check_ladspa = ladspa
  68. self.check_dssi = dssi
  69. self.check_lv2 = lv2
  70. self.check_vst = vst
  71. self.check_gig = gig
  72. self.check_sf2 = sf2
  73. self.check_sfz = sfz
  74. def setSearchToolNative(self, tool):
  75. self.tool_native = tool
  76. def setLastLoadedBinary(self, binary):
  77. self.settings_db.setValue("Plugins/LastLoadedBinary", binary)
  78. def checkLADSPA(self, OS, tool, isWine=False):
  79. global LADSPA_PATH
  80. ladspa_binaries = []
  81. self.ladspa_plugins = []
  82. for iPATH in LADSPA_PATH:
  83. binaries = findBinaries(iPATH, OS)
  84. for binary in binaries:
  85. if binary not in ladspa_binaries:
  86. ladspa_binaries.append(binary)
  87. ladspa_binaries.sort()
  88. for i in range(len(ladspa_binaries)):
  89. ladspa = ladspa_binaries[i]
  90. if os.path.basename(ladspa) in self.blacklist:
  91. print("plugin %s is blacklisted, skip it" % ladspa)
  92. continue
  93. else:
  94. percent = ( float(i) / len(ladspa_binaries) ) * self.m_percent_value
  95. self.pluginLook((self.m_last_value + percent) * 0.9, ladspa)
  96. self.setLastLoadedBinary(ladspa)
  97. plugins = checkPluginLADSPA(ladspa, tool, isWine)
  98. if plugins:
  99. self.ladspa_plugins.append(plugins)
  100. self.m_last_value += self.m_percent_value
  101. self.setLastLoadedBinary("")
  102. def checkDSSI(self, OS, tool, isWine=False):
  103. global DSSI_PATH
  104. dssi_binaries = []
  105. self.dssi_plugins = []
  106. for iPATH in DSSI_PATH:
  107. binaries = findBinaries(iPATH, OS)
  108. for binary in binaries:
  109. if binary not in dssi_binaries:
  110. dssi_binaries.append(binary)
  111. dssi_binaries.sort()
  112. for i in range(len(dssi_binaries)):
  113. dssi = dssi_binaries[i]
  114. if os.path.basename(dssi) in self.blacklist:
  115. print("plugin %s is blacklisted, skip it" % dssi)
  116. continue
  117. else:
  118. percent = ( float(i) / len(dssi_binaries) ) * self.m_percent_value
  119. self.pluginLook(self.m_last_value + percent, dssi)
  120. self.setLastLoadedBinary(dssi)
  121. plugins = checkPluginDSSI(dssi, tool, isWine)
  122. if plugins:
  123. self.dssi_plugins.append(plugins)
  124. self.m_last_value += self.m_percent_value
  125. self.setLastLoadedBinary("")
  126. def checkLV2(self, tool, isWine=False):
  127. global LV2_PATH
  128. lv2_bundles = []
  129. self.lv2_plugins = []
  130. self.pluginLook(self.m_last_value, "LV2 bundles...")
  131. for iPATH in LV2_PATH:
  132. bundles = findLV2Bundles(iPATH)
  133. for bundle in bundles:
  134. if bundle not in lv2_bundles:
  135. lv2_bundles.append(bundle)
  136. lv2_bundles.sort()
  137. for i in range(len(lv2_bundles)):
  138. lv2 = lv2_bundles[i]
  139. if (os.path.basename(lv2) in self.blacklist):
  140. print("bundle %s is blacklisted, skip it" % lv2)
  141. continue
  142. else:
  143. percent = ( float(i) / len(lv2_bundles) ) * self.m_percent_value
  144. self.pluginLook(self.m_last_value + percent, lv2)
  145. self.setLastLoadedBinary(lv2)
  146. plugins = checkPluginLV2(lv2, tool, isWine)
  147. if plugins:
  148. self.lv2_plugins.append(plugins)
  149. self.m_last_value += self.m_percent_value
  150. self.setLastLoadedBinary("")
  151. def checkVST(self, OS, tool, isWine=False):
  152. global VST_PATH
  153. vst_binaries = []
  154. self.vst_plugins = []
  155. for iPATH in VST_PATH:
  156. binaries = findBinaries(iPATH, OS)
  157. for binary in binaries:
  158. if binary not in vst_binaries:
  159. vst_binaries.append(binary)
  160. vst_binaries.sort()
  161. for i in range(len(vst_binaries)):
  162. vst = vst_binaries[i]
  163. if os.path.basename(vst) in self.blacklist:
  164. print("plugin %s is blacklisted, skip it" % vst)
  165. continue
  166. else:
  167. percent = ( float(i) / len(vst_binaries) ) * self.m_percent_value
  168. self.pluginLook(self.m_last_value + percent, vst)
  169. self.setLastLoadedBinary(vst)
  170. plugins = checkPluginVST(vst, tool, isWine)
  171. if plugins:
  172. self.vst_plugins.append(plugins)
  173. self.m_last_value += self.m_percent_value
  174. self.setLastLoadedBinary("")
  175. def checkKIT(self, kPATH, kType):
  176. kit_files = []
  177. self.kit_plugins = []
  178. for iPATH in kPATH:
  179. files = findSoundKits(iPATH, kType)
  180. for file_ in files:
  181. if file_ not in kit_files:
  182. kit_files.append(file_)
  183. kit_files.sort()
  184. for i in range(len(kit_files)):
  185. kit = kit_files[i]
  186. if os.path.basename(kit) in self.blacklist:
  187. print("plugin %s is blacklisted, skip it" % kit)
  188. continue
  189. else:
  190. percent = ( float(i) / len(kit_files) ) * self.m_percent_value
  191. self.pluginLook(self.m_last_value + percent, kit)
  192. self.setLastLoadedBinary(kit)
  193. if kType == "gig":
  194. plugins = checkPluginGIG(kit, self.tool_native)
  195. elif kType == "sf2":
  196. plugins = checkPluginSF2(kit, self.tool_native)
  197. elif kType == "sfz":
  198. plugins = checkPluginSFZ(kit, self.tool_native)
  199. else:
  200. plugins = None
  201. if plugins:
  202. self.kit_plugins.append(plugins)
  203. self.m_last_value += self.m_percent_value
  204. self.setLastLoadedBinary("")
  205. def run(self):
  206. global LADSPA_PATH, DSSI_PATH, LV2_PATH, VST_PATH, GIG_PATH, SF2_PATH, SFZ_PATH
  207. os.environ['LADSPA_PATH'] = splitter.join(LADSPA_PATH)
  208. os.environ['DSSI_PATH'] = splitter.join(DSSI_PATH)
  209. os.environ['LV2_PATH'] = splitter.join(LV2_PATH)
  210. os.environ['VST_PATH'] = splitter.join(VST_PATH)
  211. os.environ['GIG_PATH'] = splitter.join(GIG_PATH)
  212. os.environ['SF2_PATH'] = splitter.join(SF2_PATH)
  213. os.environ['SFZ_PATH'] = splitter.join(SFZ_PATH)
  214. self.blacklist = toList(self.settings_db.value("Plugins/Blacklisted", []))
  215. self.m_count = 0
  216. plugin_count = 0
  217. if self.check_ladspa: plugin_count += 1
  218. if self.check_dssi: plugin_count += 1
  219. if self.check_lv2: plugin_count += 1
  220. if self.check_vst: plugin_count += 1
  221. if self.check_native:
  222. self.m_count += plugin_count
  223. if self.check_posix32:
  224. self.m_count += plugin_count
  225. if self.check_posix64:
  226. self.m_count += plugin_count
  227. if self.check_win32:
  228. self.m_count += plugin_count
  229. if self.check_win64:
  230. self.m_count += plugin_count
  231. if self.tool_native:
  232. if self.check_gig: self.m_count += 1
  233. if self.check_sf2: self.m_count += 1
  234. if self.check_sfz: self.m_count += 1
  235. else:
  236. self.check_gig = False
  237. self.check_sf2 = False
  238. self.check_sfz = False
  239. if self.m_count == 0:
  240. return
  241. self.m_last_value = 0
  242. self.m_percent_value = 100 / self.m_count
  243. if HAIKU:
  244. OS = "HAIKU"
  245. elif LINUX:
  246. OS = "LINUX"
  247. elif MACOS:
  248. OS = "MACOS"
  249. elif WINDOWS:
  250. OS = "WINDOWS"
  251. else:
  252. OS = "UNKNOWN"
  253. if self.check_ladspa:
  254. m_value = 0
  255. if haveLRDF:
  256. if self.check_native: m_value += 0.1
  257. if self.check_posix32: m_value += 0.1
  258. if self.check_posix64: m_value += 0.1
  259. if self.check_win32: m_value += 0.1
  260. if self.check_win64: m_value += 0.1
  261. rdf_pad_value = self.m_percent_value * m_value
  262. if self.check_native:
  263. self.checkLADSPA(OS, carla_discovery_native)
  264. self.settings_db.setValue("Plugins/LADSPA_native", self.ladspa_plugins)
  265. self.settings_db.sync()
  266. if self.check_posix32:
  267. self.checkLADSPA(OS, carla_discovery_posix32)
  268. self.settings_db.setValue("Plugins/LADSPA_posix32", self.ladspa_plugins)
  269. self.settings_db.sync()
  270. if self.check_posix64:
  271. self.checkLADSPA(OS, carla_discovery_posix64)
  272. self.settings_db.setValue("Plugins/LADSPA_posix64", self.ladspa_plugins)
  273. self.settings_db.sync()
  274. if self.check_win32:
  275. self.checkLADSPA("WINDOWS", carla_discovery_win32, not WINDOWS)
  276. self.settings_db.setValue("Plugins/LADSPA_win32", self.ladspa_plugins)
  277. self.settings_db.sync()
  278. if self.check_win64:
  279. self.checkLADSPA("WINDOWS", carla_discovery_win64, not WINDOWS)
  280. self.settings_db.setValue("Plugins/LADSPA_win64", self.ladspa_plugins)
  281. self.settings_db.sync()
  282. if haveLRDF:
  283. if m_value > 0:
  284. start_value = self.m_last_value - rdf_pad_value
  285. self.pluginLook(start_value, "LADSPA RDFs...")
  286. ladspa_rdf_info = ladspa_rdf.recheck_all_plugins(self, start_value, self.m_percent_value, m_value)
  287. SettingsDir = os.path.join(HOME, ".config", "Cadence")
  288. f_ladspa = open(os.path.join(SettingsDir, "ladspa_rdf.db"), 'w')
  289. json.dump(ladspa_rdf_info, f_ladspa)
  290. f_ladspa.close()
  291. if self.check_dssi:
  292. if self.check_native:
  293. self.checkDSSI(OS, carla_discovery_native)
  294. self.settings_db.setValue("Plugins/DSSI_native", self.dssi_plugins)
  295. self.settings_db.sync()
  296. if self.check_posix32:
  297. self.checkDSSI(OS, carla_discovery_posix32)
  298. self.settings_db.setValue("Plugins/DSSI_posix32", self.dssi_plugins)
  299. self.settings_db.sync()
  300. if self.check_posix64:
  301. self.checkDSSI(OS, carla_discovery_posix64)
  302. self.settings_db.setValue("Plugins/DSSI_posix64", self.dssi_plugins)
  303. self.settings_db.sync()
  304. if self.check_win32:
  305. self.checkDSSI("WINDOWS", carla_discovery_win32, not WINDOWS)
  306. self.settings_db.setValue("Plugins/DSSI_win32", self.dssi_plugins)
  307. self.settings_db.sync()
  308. if self.check_win64:
  309. self.checkDSSI("WINDOWS", carla_discovery_win64, not WINDOWS)
  310. self.settings_db.setValue("Plugins/DSSI_win64", self.dssi_plugins)
  311. self.settings_db.sync()
  312. if self.check_lv2:
  313. if self.check_native:
  314. self.checkLV2(carla_discovery_native)
  315. self.settings_db.setValue("Plugins/LV2_native", self.lv2_plugins)
  316. self.settings_db.sync()
  317. if self.check_posix32:
  318. self.checkLV2(carla_discovery_posix32)
  319. self.settings_db.setValue("Plugins/LV2_posix32", self.lv2_plugins)
  320. self.settings_db.sync()
  321. if self.check_posix64:
  322. self.checkLV2(carla_discovery_posix64)
  323. self.settings_db.setValue("Plugins/LV2_posix64", self.lv2_plugins)
  324. self.settings_db.sync()
  325. if self.check_win32:
  326. self.checkLV2(carla_discovery_win32, not WINDOWS)
  327. self.settings_db.setValue("Plugins/LV2_win32", self.lv2_plugins)
  328. self.settings_db.sync()
  329. if self.check_win64:
  330. self.checkLV2(carla_discovery_win64, not WINDOWS)
  331. self.settings_db.setValue("Plugins/LV2_win64", self.lv2_plugins)
  332. self.settings_db.sync()
  333. if self.check_vst:
  334. if self.check_native:
  335. self.checkVST(OS, carla_discovery_native)
  336. self.settings_db.setValue("Plugins/VST_native", self.vst_plugins)
  337. self.settings_db.sync()
  338. if self.check_posix32:
  339. self.checkVST(OS, carla_discovery_posix32)
  340. self.settings_db.setValue("Plugins/VST_posix32", self.vst_plugins)
  341. self.settings_db.sync()
  342. if self.check_posix64:
  343. self.checkVST(OS, carla_discovery_posix64)
  344. self.settings_db.setValue("Plugins/VST_posix64", self.vst_plugins)
  345. self.settings_db.sync()
  346. if self.check_win32:
  347. self.checkVST("WINDOWS", carla_discovery_win32, not WINDOWS)
  348. self.settings_db.setValue("Plugins/VST_win32", self.vst_plugins)
  349. self.settings_db.sync()
  350. if self.check_win64:
  351. self.checkVST("WINDOWS", carla_discovery_win64, not WINDOWS)
  352. self.settings_db.setValue("Plugins/VST_win64", self.vst_plugins)
  353. self.settings_db.sync()
  354. if self.check_gig:
  355. self.checkKIT(GIG_PATH, "gig")
  356. self.settings_db.setValue("Plugins/GIG", self.kit_plugins)
  357. self.settings_db.sync()
  358. if self.check_sf2:
  359. self.checkKIT(SF2_PATH, "sf2")
  360. self.settings_db.setValue("Plugins/SF2", self.kit_plugins)
  361. self.settings_db.sync()
  362. if self.check_sfz:
  363. self.checkKIT(SFZ_PATH, "sfz")
  364. self.settings_db.setValue("Plugins/SFZ", self.kit_plugins)
  365. self.settings_db.sync()
  366. # Plugin Refresh Dialog
  367. class PluginRefreshW(QDialog, ui_carla_refresh.Ui_PluginRefreshW):
  368. def __init__(self, parent):
  369. QDialog.__init__(self, parent)
  370. self.setupUi(self)
  371. self.b_skip.setVisible(False)
  372. if HAIKU:
  373. self.ch_posix32.setText("Haiku 32bit")
  374. self.ch_posix64.setText("Haiku 64bit")
  375. elif LINUX:
  376. self.ch_posix32.setText("Linux 32bit")
  377. self.ch_posix64.setText("Linux 64bit")
  378. elif MACOS:
  379. self.ch_posix32.setText("MacOS 32bit")
  380. self.ch_posix64.setText("MacOS 64bit")
  381. self.settings = self.parent().settings
  382. self.settings_db = self.parent().settings_db
  383. self.loadSettings()
  384. self.pThread = SearchPluginsThread(self)
  385. if carla_discovery_posix32 and not WINDOWS:
  386. self.ico_posix32.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  387. else:
  388. self.ico_posix32.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  389. self.ch_posix32.setChecked(False)
  390. self.ch_posix32.setEnabled(False)
  391. if carla_discovery_posix64 and not WINDOWS:
  392. self.ico_posix64.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  393. else:
  394. self.ico_posix64.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  395. self.ch_posix64.setChecked(False)
  396. self.ch_posix64.setEnabled(False)
  397. if carla_discovery_win32:
  398. self.ico_win32.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  399. else:
  400. self.ico_win32.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  401. self.ch_win32.setChecked(False)
  402. self.ch_win32.setEnabled(False)
  403. if carla_discovery_win64:
  404. self.ico_win64.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  405. else:
  406. self.ico_win64.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  407. self.ch_win64.setChecked(False)
  408. self.ch_win64.setEnabled(False)
  409. if haveLRDF:
  410. self.ico_rdflib.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  411. else:
  412. self.ico_rdflib.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  413. hasNative = bool(carla_discovery_native)
  414. hasNonNative = False
  415. if WINDOWS:
  416. if is64bit:
  417. hasNative = bool(carla_discovery_win64)
  418. hasNonNative = bool(carla_discovery_win32)
  419. self.pThread.setSearchToolNative(carla_discovery_win64)
  420. self.ch_win64.setChecked(False)
  421. self.ch_win64.setVisible(False)
  422. self.ico_win64.setVisible(False)
  423. self.label_win64.setVisible(False)
  424. else:
  425. hasNative = bool(carla_discovery_win32)
  426. hasNonNative = bool(carla_discovery_win64)
  427. self.pThread.setSearchToolNative(carla_discovery_win32)
  428. self.ch_win32.setChecked(False)
  429. self.ch_win32.setVisible(False)
  430. self.ico_win32.setVisible(False)
  431. self.label_win32.setVisible(False)
  432. elif LINUX or MACOS:
  433. if is64bit:
  434. hasNonNative = bool(carla_discovery_posix32 or carla_discovery_win32 or carla_discovery_win64)
  435. self.ch_posix64.setChecked(False)
  436. self.ch_posix64.setVisible(False)
  437. self.ico_posix64.setVisible(False)
  438. self.label_posix64.setVisible(False)
  439. else:
  440. hasNonNative = bool(carla_discovery_posix64 or carla_discovery_win32 or carla_discovery_win64)
  441. self.ch_posix32.setChecked(False)
  442. self.ch_posix32.setVisible(False)
  443. self.ico_posix32.setVisible(False)
  444. self.label_posix32.setVisible(False)
  445. if hasNative:
  446. self.ico_native.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  447. else:
  448. self.ico_native.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  449. self.ch_native.setChecked(False)
  450. self.ch_native.setEnabled(False)
  451. self.ch_gig.setChecked(False)
  452. self.ch_gig.setEnabled(False)
  453. self.ch_sf2.setChecked(False)
  454. self.ch_sf2.setEnabled(False)
  455. self.ch_sfz.setChecked(False)
  456. self.ch_sfz.setEnabled(False)
  457. if not hasNonNative:
  458. self.ch_ladspa.setChecked(False)
  459. self.ch_ladspa.setEnabled(False)
  460. self.ch_dssi.setChecked(False)
  461. self.ch_dssi.setEnabled(False)
  462. self.ch_vst.setChecked(False)
  463. self.ch_vst.setEnabled(False)
  464. self.b_start.setEnabled(False)
  465. self.connect(self.b_start, SIGNAL("clicked()"), SLOT("slot_start()"))
  466. self.connect(self.b_skip, SIGNAL("clicked()"), SLOT("slot_skip()"))
  467. self.connect(self.pThread, SIGNAL("PluginLook(int, QString)"), SLOT("slot_handlePluginLook(int, QString)"))
  468. self.connect(self.pThread, SIGNAL("finished()"), SLOT("slot_handlePluginThreadFinished()"))
  469. @pyqtSlot()
  470. def slot_start(self):
  471. self.progressBar.setMinimum(0)
  472. self.progressBar.setMaximum(100)
  473. self.progressBar.setValue(0)
  474. self.b_start.setEnabled(False)
  475. self.b_skip.setVisible(True)
  476. self.b_close.setVisible(False)
  477. native, posix32, posix64, win32, win64 = (self.ch_native.isChecked(), self.ch_posix32.isChecked(), self.ch_posix64.isChecked(), self.ch_win32.isChecked(), self.ch_win64.isChecked())
  478. ladspa, dssi, lv2, vst, gig, sf2, sfz = (self.ch_ladspa.isChecked(), self.ch_dssi.isChecked(), self.ch_lv2.isChecked(), self.ch_vst.isChecked(),
  479. self.ch_gig.isChecked(), self.ch_sf2.isChecked(), self.ch_sfz.isChecked())
  480. self.pThread.setSearchBinaryTypes(native, posix32, posix64, win32, win64)
  481. self.pThread.setSearchPluginTypes(ladspa, dssi, lv2, vst, gig, sf2, sfz)
  482. self.pThread.start()
  483. @pyqtSlot()
  484. def slot_skip(self):
  485. self.pThread.skipPlugin()
  486. @pyqtSlot(int, str)
  487. def slot_handlePluginLook(self, percent, plugin):
  488. self.progressBar.setFormat("%s" % plugin)
  489. self.progressBar.setValue(percent)
  490. @pyqtSlot()
  491. def slot_handlePluginThreadFinished(self):
  492. self.progressBar.setMinimum(0)
  493. self.progressBar.setMaximum(1)
  494. self.progressBar.setValue(1)
  495. self.progressBar.setFormat(self.tr("Done"))
  496. self.b_start.setEnabled(True)
  497. self.b_skip.setVisible(False)
  498. self.b_close.setVisible(True)
  499. def saveSettings(self):
  500. self.settings.setValue("PluginDatabase/SearchLADSPA", self.ch_ladspa.isChecked())
  501. self.settings.setValue("PluginDatabase/SearchDSSI", self.ch_dssi.isChecked())
  502. self.settings.setValue("PluginDatabase/SearchLV2", self.ch_lv2.isChecked())
  503. self.settings.setValue("PluginDatabase/SearchVST", self.ch_vst.isChecked())
  504. self.settings.setValue("PluginDatabase/SearchGIG", self.ch_gig.isChecked())
  505. self.settings.setValue("PluginDatabase/SearchSF2", self.ch_sf2.isChecked())
  506. self.settings.setValue("PluginDatabase/SearchSFZ", self.ch_sfz.isChecked())
  507. self.settings.setValue("PluginDatabase/SearchNative", self.ch_native.isChecked())
  508. self.settings.setValue("PluginDatabase/SearchPOSIX32", self.ch_posix32.isChecked())
  509. self.settings.setValue("PluginDatabase/SearchPOSIX64", self.ch_posix64.isChecked())
  510. self.settings.setValue("PluginDatabase/SearchWin32", self.ch_win32.isChecked())
  511. self.settings.setValue("PluginDatabase/SearchWin64", self.ch_win64.isChecked())
  512. self.settings_db.setValue("Plugins/LastLoadedBinary", "")
  513. def loadSettings(self):
  514. self.ch_ladspa.setChecked(self.settings.value("PluginDatabase/SearchLADSPA", True, type=bool))
  515. self.ch_dssi.setChecked(self.settings.value("PluginDatabase/SearchDSSI", True, type=bool))
  516. self.ch_lv2.setChecked(self.settings.value("PluginDatabase/SearchLV2", True, type=bool))
  517. self.ch_vst.setChecked(self.settings.value("PluginDatabase/SearchVST", True, type=bool))
  518. self.ch_gig.setChecked(self.settings.value("PluginDatabase/SearchGIG", True, type=bool))
  519. self.ch_sf2.setChecked(self.settings.value("PluginDatabase/SearchSF2", True, type=bool))
  520. self.ch_sfz.setChecked(self.settings.value("PluginDatabase/SearchSFZ", True, type=bool))
  521. self.ch_native.setChecked(self.settings.value("PluginDatabase/SearchNative", True, type=bool))
  522. self.ch_posix32.setChecked(self.settings.value("PluginDatabase/SearchPOSIX32", False, type=bool))
  523. self.ch_posix64.setChecked(self.settings.value("PluginDatabase/SearchPOSIX64", False, type=bool))
  524. self.ch_win32.setChecked(self.settings.value("PluginDatabase/SearchWin32", False, type=bool))
  525. self.ch_win64.setChecked(self.settings.value("PluginDatabase/SearchWin64", False, type=bool))
  526. def closeEvent(self, event):
  527. if self.pThread.isRunning():
  528. self.pThread.terminate()
  529. self.pThread.wait()
  530. self.saveSettings()
  531. QDialog.closeEvent(self, event)
  532. def done(self, r):
  533. QDialog.done(self, r)
  534. self.close()
  535. # Plugin Database Dialog
  536. class PluginDatabaseW(QDialog, ui_carla_database.Ui_PluginDatabaseW):
  537. def __init__(self, parent):
  538. QDialog.__init__(self, parent)
  539. self.setupUi(self)
  540. self.warning_old_shown = False
  541. self.b_add.setEnabled(False)
  542. if BINARY_NATIVE in (BINARY_POSIX32, BINARY_WIN32):
  543. self.ch_bridged.setText(self.tr("Bridged (64bit)"))
  544. else:
  545. self.ch_bridged.setText(self.tr("Bridged (32bit)"))
  546. self.settings = self.parent().settings
  547. self.settings_db = self.parent().settings_db
  548. self.loadSettings()
  549. if not (LINUX or MACOS):
  550. self.ch_bridged_wine.setChecked(False)
  551. self.ch_bridged_wine.setEnabled(False)
  552. # Blacklist plugins
  553. if not self.settings_db.contains("Plugins/Blacklisted"):
  554. blacklist = [] # FIXME
  555. # Broken or useless plugins
  556. #blacklist.append("dssi-vst.so")
  557. blacklist.append("liteon_biquad-vst.so")
  558. blacklist.append("liteon_biquad-vst_64bit.so")
  559. blacklist.append("fx_blur-vst.so")
  560. blacklist.append("fx_blur-vst_64bit.so")
  561. blacklist.append("fx_tempodelay-vst.so")
  562. blacklist.append("Scrubby_64bit.so")
  563. blacklist.append("Skidder_64bit.so")
  564. blacklist.append("libwormhole2_64bit.so")
  565. blacklist.append("vexvst.so")
  566. #blacklist.append("deckadance.dll")
  567. self.settings_db.setValue("Plugins/Blacklisted", blacklist)
  568. self.connect(self.b_add, SIGNAL("clicked()"), SLOT("slot_add_plugin()"))
  569. self.connect(self.b_refresh, SIGNAL("clicked()"), SLOT("slot_refresh_plugins()"))
  570. self.connect(self.tb_filters, SIGNAL("clicked()"), SLOT("slot_maybe_show_filters()"))
  571. self.connect(self.tableWidget, SIGNAL("currentCellChanged(int, int, int, int)"), SLOT("slot_checkPlugin(int)"))
  572. self.connect(self.tableWidget, SIGNAL("cellDoubleClicked(int, int)"), SLOT("slot_add_plugin()"))
  573. self.connect(self.lineEdit, SIGNAL("textChanged(QString)"), SLOT("slot_checkFilters()"))
  574. self.connect(self.ch_effects, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  575. self.connect(self.ch_instruments, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  576. self.connect(self.ch_midi, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  577. self.connect(self.ch_other, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  578. self.connect(self.ch_kits, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  579. self.connect(self.ch_ladspa, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  580. self.connect(self.ch_dssi, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  581. self.connect(self.ch_lv2, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  582. self.connect(self.ch_vst, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  583. self.connect(self.ch_native, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  584. self.connect(self.ch_bridged, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  585. self.connect(self.ch_bridged_wine, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  586. self.connect(self.ch_gui, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  587. self.connect(self.ch_stereo, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  588. self.ret_plugin = None
  589. def showFilters(self, yesno):
  590. self.tb_filters.setArrowType(Qt.UpArrow if yesno else Qt.DownArrow)
  591. self.frame.setVisible(yesno)
  592. def reAddPlugins(self):
  593. row_count = self.tableWidget.rowCount()
  594. for x in range(row_count):
  595. self.tableWidget.removeRow(0)
  596. self.last_table_index = 0
  597. self.tableWidget.setSortingEnabled(False)
  598. ladspa_plugins = []
  599. ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_native", []))
  600. ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_posix32", []))
  601. ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_posix64", []))
  602. ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_win32", []))
  603. ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_win64", []))
  604. dssi_plugins = []
  605. dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_native", []))
  606. dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_posix32", []))
  607. dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_posix64", []))
  608. dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_win32", []))
  609. dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_win64", []))
  610. lv2_plugins = []
  611. lv2_plugins += toList(self.settings_db.value("Plugins/LV2_native", []))
  612. lv2_plugins += toList(self.settings_db.value("Plugins/LV2_posix32", []))
  613. lv2_plugins += toList(self.settings_db.value("Plugins/LV2_posix64", []))
  614. lv2_plugins += toList(self.settings_db.value("Plugins/LV2_win32", []))
  615. lv2_plugins += toList(self.settings_db.value("Plugins/LV2_win64", []))
  616. vst_plugins = []
  617. vst_plugins += toList(self.settings_db.value("Plugins/VST_native", []))
  618. vst_plugins += toList(self.settings_db.value("Plugins/VST_posix32", []))
  619. vst_plugins += toList(self.settings_db.value("Plugins/VST_posix64", []))
  620. vst_plugins += toList(self.settings_db.value("Plugins/VST_win32", []))
  621. vst_plugins += toList(self.settings_db.value("Plugins/VST_win64", []))
  622. gigs = toList(self.settings_db.value("Plugins/GIG", []))
  623. sf2s = toList(self.settings_db.value("Plugins/SF2", []))
  624. sfzs = toList(self.settings_db.value("Plugins/SFZ", []))
  625. ladspa_count = 0
  626. dssi_count = 0
  627. lv2_count = 0
  628. vst_count = 0
  629. kit_count = 0
  630. for plugins in ladspa_plugins:
  631. for plugin in plugins:
  632. self.addPluginToTable(plugin, "LADSPA")
  633. ladspa_count += 1
  634. for plugins in dssi_plugins:
  635. for plugin in plugins:
  636. self.addPluginToTable(plugin, "DSSI")
  637. dssi_count += 1
  638. for plugins in lv2_plugins:
  639. for plugin in plugins:
  640. self.addPluginToTable(plugin, "LV2")
  641. lv2_count += 1
  642. for plugins in vst_plugins:
  643. for plugin in plugins:
  644. self.addPluginToTable(plugin, "VST")
  645. vst_count += 1
  646. for gig in gigs:
  647. for gig_i in gig:
  648. self.addPluginToTable(gig_i, "GIG")
  649. kit_count += 1
  650. for sf2 in sf2s:
  651. for sf2_i in sf2:
  652. self.addPluginToTable(sf2_i, "SF2")
  653. kit_count += 1
  654. for sfz in sfzs:
  655. for sfz_i in sfz:
  656. self.addPluginToTable(sfz_i, "SFZ")
  657. kit_count += 1
  658. self.slot_checkFilters()
  659. self.tableWidget.setSortingEnabled(True)
  660. self.tableWidget.sortByColumn(0, Qt.AscendingOrder)
  661. self.label.setText(self.tr("Have %i LADSPA, %i DSSI, %i LV2, %i VST and %i Sound Kits" % (ladspa_count, dssi_count, lv2_count, vst_count, kit_count)))
  662. def addPluginToTable(self, plugin, ptype):
  663. index = self.last_table_index
  664. if "build" not in plugin.keys():
  665. if not self.warning_old_shown:
  666. QMessageBox.warning(self, self.tr("Warning"), self.tr("You're using a Carla-Database from an old version of Carla, please update *all* the plugins"))
  667. self.warning_old_shown = True
  668. return
  669. if plugin['build'] == BINARY_NATIVE:
  670. bridge_text = self.tr("No")
  671. else:
  672. type_text = self.tr("Unknown")
  673. if LINUX or MACOS:
  674. if plugin['build'] == BINARY_POSIX32:
  675. type_text = "32bit"
  676. elif plugin['build'] == BINARY_POSIX64:
  677. type_text = "64bit"
  678. elif plugin['build'] == BINARY_WIN32:
  679. type_text = "Windows 32bit"
  680. elif plugin['build'] == BINARY_WIN64:
  681. type_text = "Windows 64bit"
  682. elif WINDOWS:
  683. if plugin['build'] == BINARY_WIN32:
  684. type_text = "32bit"
  685. elif plugin['build'] == BINARY_WIN64:
  686. type_text = "64bit"
  687. bridge_text = self.tr("Yes (%s)" % type_text)
  688. self.tableWidget.insertRow(index)
  689. self.tableWidget.setItem(index, 0, QTableWidgetItem(plugin['name']))
  690. self.tableWidget.setItem(index, 1, QTableWidgetItem(plugin['label']))
  691. self.tableWidget.setItem(index, 2, QTableWidgetItem(plugin['maker']))
  692. self.tableWidget.setItem(index, 3, QTableWidgetItem(str(plugin['unique_id'])))
  693. self.tableWidget.setItem(index, 4, QTableWidgetItem(str(plugin['audio.ins'])))
  694. self.tableWidget.setItem(index, 5, QTableWidgetItem(str(plugin['audio.outs'])))
  695. self.tableWidget.setItem(index, 6, QTableWidgetItem(str(plugin['parameters.ins'])))
  696. self.tableWidget.setItem(index, 7, QTableWidgetItem(str(plugin['parameters.outs'])))
  697. self.tableWidget.setItem(index, 8, QTableWidgetItem(str(plugin['programs.total'])))
  698. self.tableWidget.setItem(index, 9, QTableWidgetItem(self.tr("Yes") if (plugin['hints'] & PLUGIN_HAS_GUI) else self.tr("No")))
  699. self.tableWidget.setItem(index, 10, QTableWidgetItem(self.tr("Yes") if (plugin['hints'] & PLUGIN_IS_SYNTH) else self.tr("No")))
  700. self.tableWidget.setItem(index, 11, QTableWidgetItem(bridge_text))
  701. self.tableWidget.setItem(index, 12, QTableWidgetItem(ptype))
  702. self.tableWidget.setItem(index, 13, QTableWidgetItem(plugin['binary']))
  703. self.tableWidget.item(self.last_table_index, 0).plugin_data = plugin
  704. self.last_table_index += 1
  705. @pyqtSlot()
  706. def slot_add_plugin(self):
  707. if self.tableWidget.currentRow() >= 0:
  708. self.ret_plugin = self.tableWidget.item(self.tableWidget.currentRow(), 0).plugin_data
  709. self.accept()
  710. else:
  711. self.reject()
  712. @pyqtSlot()
  713. def slot_refresh_plugins(self):
  714. lastLoadedPlugin = self.settings_db.value("Plugins/LastLoadedBinary", "", type=str)
  715. if lastLoadedPlugin:
  716. lastLoadedPlugin = os.path.basename(lastLoadedPlugin)
  717. ask = QMessageBox.question(self, self.tr("Warning"), self.tr("There was an error while checking the plugin %s.\n"
  718. "Do you want to blacklist it?" % lastLoadedPlugin),
  719. QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
  720. if ask == QMessageBox.Yes:
  721. blacklist = toList(self.settings_db.value("Plugins/Blacklisted", []))
  722. blacklist.append(lastLoadedPlugin)
  723. self.settings_db.setValue("Plugins/Blacklisted", blacklist)
  724. #self.label.setText(self.tr("Looking for plugins..."))
  725. PluginRefreshW(self).exec_()
  726. self.reAddPlugins()
  727. self.parent().loadRDFs()
  728. @pyqtSlot()
  729. def slot_maybe_show_filters(self):
  730. self.showFilters(not self.frame.isVisible())
  731. @pyqtSlot(int)
  732. def slot_checkPlugin(self, row):
  733. self.b_add.setEnabled(row >= 0)
  734. @pyqtSlot()
  735. def slot_checkFilters(self):
  736. text = self.lineEdit.text().lower()
  737. hide_effects = not self.ch_effects.isChecked()
  738. hide_instruments = not self.ch_instruments.isChecked()
  739. hide_midi = not self.ch_midi.isChecked()
  740. hide_other = not self.ch_other.isChecked()
  741. hide_ladspa = not self.ch_ladspa.isChecked()
  742. hide_dssi = not self.ch_dssi.isChecked()
  743. hide_lv2 = not self.ch_lv2.isChecked()
  744. hide_vst = not self.ch_vst.isChecked()
  745. hide_kits = not self.ch_kits.isChecked()
  746. hide_native = not self.ch_native.isChecked()
  747. hide_bridged = not self.ch_bridged.isChecked()
  748. hide_bridged_wine = not self.ch_bridged_wine.isChecked()
  749. hide_non_gui = self.ch_gui.isChecked()
  750. hide_non_stereo = self.ch_stereo.isChecked()
  751. if HAIKU or LINUX or MACOS:
  752. native_bins = [BINARY_POSIX32, BINARY_POSIX64]
  753. wine_bins = [BINARY_WIN32, BINARY_WIN64]
  754. elif WINDOWS:
  755. native_bins = [BINARY_WIN32, BINARY_WIN64]
  756. wine_bins = []
  757. else:
  758. native_bins = []
  759. wine_bins = []
  760. row_count = self.tableWidget.rowCount()
  761. for i in range(row_count):
  762. self.tableWidget.showRow(i)
  763. plugin = self.tableWidget.item(i, 0).plugin_data
  764. ains = plugin['audio.ins']
  765. aouts = plugin['audio.outs']
  766. mins = plugin['midi.ins']
  767. mouts = plugin['midi.outs']
  768. ptype = self.tableWidget.item(i, 12).text()
  769. is_synth = bool(plugin['hints'] & PLUGIN_IS_SYNTH)
  770. is_effect = bool(ains > 0 < aouts and not is_synth)
  771. is_midi = bool(ains == 0 and aouts == 0 and mins > 0 < mouts)
  772. is_kit = bool(ptype in ("GIG", "SF2", "SFZ"))
  773. is_other = bool(not (is_effect or is_synth or is_midi or is_kit))
  774. is_native = bool(plugin['build'] == BINARY_NATIVE)
  775. is_stereo = bool(ains == 2 and aouts == 2) or (is_synth and aouts == 2)
  776. has_gui = bool(plugin['hints'] & PLUGIN_HAS_GUI)
  777. is_bridged = bool(not is_native and plugin['build'] in native_bins)
  778. is_bridged_wine = bool(not is_native and plugin['build'] in wine_bins)
  779. if (hide_effects and is_effect):
  780. self.tableWidget.hideRow(i)
  781. elif (hide_instruments and is_synth):
  782. self.tableWidget.hideRow(i)
  783. elif (hide_midi and is_midi):
  784. self.tableWidget.hideRow(i)
  785. elif (hide_other and is_other):
  786. self.tableWidget.hideRow(i)
  787. elif (hide_kits and is_kit):
  788. self.tableWidget.hideRow(i)
  789. elif (hide_ladspa and ptype == "LADSPA"):
  790. self.tableWidget.hideRow(i)
  791. elif (hide_dssi and ptype == "DSSI"):
  792. self.tableWidget.hideRow(i)
  793. elif (hide_lv2 and ptype == "LV2"):
  794. self.tableWidget.hideRow(i)
  795. elif (hide_vst and ptype == "VST"):
  796. self.tableWidget.hideRow(i)
  797. elif (hide_native and is_native):
  798. self.tableWidget.hideRow(i)
  799. elif (hide_bridged and is_bridged):
  800. self.tableWidget.hideRow(i)
  801. elif (hide_bridged_wine and is_bridged_wine):
  802. self.tableWidget.hideRow(i)
  803. elif (hide_non_gui and not has_gui):
  804. self.tableWidget.hideRow(i)
  805. elif (hide_non_stereo and not is_stereo):
  806. self.tableWidget.hideRow(i)
  807. elif (text and not (
  808. text in self.tableWidget.item(i, 0).text().lower() or
  809. text in self.tableWidget.item(i, 1).text().lower() or
  810. text in self.tableWidget.item(i, 2).text().lower() or
  811. text in self.tableWidget.item(i, 3).text().lower() or
  812. text in self.tableWidget.item(i, 13).text().lower())):
  813. self.tableWidget.hideRow(i)
  814. def saveSettings(self):
  815. self.settings.setValue("PluginDatabase/Geometry", self.saveGeometry())
  816. self.settings.setValue("PluginDatabase/TableGeometry", self.tableWidget.horizontalHeader().saveState())
  817. self.settings.setValue("PluginDatabase/ShowFilters", (self.tb_filters.arrowType() == Qt.UpArrow))
  818. self.settings.setValue("PluginDatabase/ShowEffects", self.ch_effects.isChecked())
  819. self.settings.setValue("PluginDatabase/ShowInstruments", self.ch_instruments.isChecked())
  820. self.settings.setValue("PluginDatabase/ShowMIDI", self.ch_midi.isChecked())
  821. self.settings.setValue("PluginDatabase/ShowOther", self.ch_other.isChecked())
  822. self.settings.setValue("PluginDatabase/ShowLADSPA", self.ch_ladspa.isChecked())
  823. self.settings.setValue("PluginDatabase/ShowDSSI", self.ch_dssi.isChecked())
  824. self.settings.setValue("PluginDatabase/ShowLV2", self.ch_lv2.isChecked())
  825. self.settings.setValue("PluginDatabase/ShowVST", self.ch_vst.isChecked())
  826. self.settings.setValue("PluginDatabase/ShowKits", self.ch_kits.isChecked())
  827. self.settings.setValue("PluginDatabase/ShowNative", self.ch_native.isChecked())
  828. self.settings.setValue("PluginDatabase/ShowBridged", self.ch_bridged.isChecked())
  829. self.settings.setValue("PluginDatabase/ShowBridgedWine", self.ch_bridged_wine.isChecked())
  830. self.settings.setValue("PluginDatabase/ShowHasGUI", self.ch_gui.isChecked())
  831. self.settings.setValue("PluginDatabase/ShowStereoOnly", self.ch_stereo.isChecked())
  832. def loadSettings(self):
  833. self.restoreGeometry(self.settings.value("PluginDatabase/Geometry", ""))
  834. self.tableWidget.horizontalHeader().restoreState(self.settings.value("PluginDatabase/TableGeometry", ""))
  835. self.showFilters(self.settings.value("PluginDatabase/ShowFilters", False, type=bool))
  836. self.ch_effects.setChecked(self.settings.value("PluginDatabase/ShowEffects", True, type=bool))
  837. self.ch_instruments.setChecked(self.settings.value("PluginDatabase/ShowInstruments", True, type=bool))
  838. self.ch_midi.setChecked(self.settings.value("PluginDatabase/ShowMIDI", True, type=bool))
  839. self.ch_other.setChecked(self.settings.value("PluginDatabase/ShowOther", True, type=bool))
  840. self.ch_ladspa.setChecked(self.settings.value("PluginDatabase/ShowLADSPA", True, type=bool))
  841. self.ch_dssi.setChecked(self.settings.value("PluginDatabase/ShowDSSI", True, type=bool))
  842. self.ch_lv2.setChecked(self.settings.value("PluginDatabase/ShowLV2", True, type=bool))
  843. self.ch_vst.setChecked(self.settings.value("PluginDatabase/ShowVST", True, type=bool))
  844. self.ch_kits.setChecked(self.settings.value("PluginDatabase/ShowKits", True, type=bool))
  845. self.ch_native.setChecked(self.settings.value("PluginDatabase/ShowNative", True, type=bool))
  846. self.ch_bridged.setChecked(self.settings.value("PluginDatabase/ShowBridged", True, type=bool))
  847. self.ch_bridged_wine.setChecked(self.settings.value("PluginDatabase/ShowBridgedWine", True, type=bool))
  848. self.ch_gui.setChecked(self.settings.value("PluginDatabase/ShowHasGUI", False, type=bool))
  849. self.ch_stereo.setChecked(self.settings.value("PluginDatabase/ShowStereoOnly", False, type=bool))
  850. self.reAddPlugins()
  851. def closeEvent(self, event):
  852. self.saveSettings()
  853. QDialog.closeEvent(self, event)
  854. def done(self, r):
  855. QDialog.done(self, r)
  856. self.close()
  857. # About Carla Dialog
  858. class CarlaAboutW(QDialog, ui_carla_about.Ui_CarlaAboutW):
  859. def __init__(self, parent):
  860. QDialog.__init__(self, parent)
  861. self.setupUi(self)
  862. self.l_about.setText(self.tr(""
  863. "<br>Version %s"
  864. "<br>Carla is a Multi-Plugin Host for JACK.<br>"
  865. "<br>Copyright (C) 2011-2012 falkTX<br>"
  866. "<br><i>VST is a trademark of Steinberg Media Technologies GmbH.</i>"
  867. "" % VERSION))
  868. host_osc_url = cString(Carla.Host.get_host_osc_url())
  869. self.le_osc_url.setText(host_osc_url)
  870. self.l_osc_cmds.setText(
  871. " /set_active <i-value>\n"
  872. " /set_drywet <f-value>\n"
  873. " /set_volume <f-value>\n"
  874. " /set_balance_left <f-value>\n"
  875. " /set_balance_right <f-value>\n"
  876. " /set_parameter <i-index> <f-value>\n"
  877. " /set_program <i-index>\n"
  878. " /set_midi_program <i-index>\n"
  879. " /note_on <i-note> <i-velo>\n"
  880. " /note_off <i-note>\n"
  881. )
  882. self.l_example.setText("/Carla/2/set_parameter 2 0.5")
  883. self.l_example_help.setText("<i>(as in this example, \"2\" is the plugin number)</i>")
  884. self.l_ladspa.setText(self.tr("Everything! (Including LRDF)"))
  885. self.l_dssi.setText(self.tr("Everything! (Including CustomData/Chunks)"))
  886. self.l_lv2.setText(self.tr("About 95&#37; complete (only missing minor features).<br/>"
  887. "Implemented Feature/Extensions:"
  888. "<ul>"
  889. "<li>http://lv2plug.in/ns/ext/atom</li>"
  890. "<li>http://lv2plug.in/ns/ext/data-access</li>"
  891. "<li>http://lv2plug.in/ns/ext/event</li>"
  892. "<li>http://lv2plug.in/ns/ext/instance-access</li>"
  893. "<li>http://lv2plug.in/ns/ext/log</li>"
  894. "<li>http://lv2plug.in/ns/ext/midi</li>"
  895. "<li>http://lv2plug.in/ns/ext/patch</li>"
  896. "<li>http://lv2plug.in/ns/ext/port-props</li>"
  897. #"<li>http://lv2plug.in/ns/ext/presets</li>"
  898. "<li>http://lv2plug.in/ns/ext/state</li>"
  899. "<li>http://lv2plug.in/ns/ext/time</li>"
  900. "<li>http://lv2plug.in/ns/ext/uri-map</li>"
  901. "<li>http://lv2plug.in/ns/ext/urid</li>"
  902. "<li>http://lv2plug.in/ns/ext/worker</li>"
  903. "<li>http://lv2plug.in/ns/extensions/ui</li>"
  904. "<li>http://lv2plug.in/ns/extensions/units</li>"
  905. #"<li>http://home.gna.org/lv2dynparam/v1</li>"
  906. "<li>http://home.gna.org/lv2dynparam/rtmempool/v1</li>"
  907. "<li>http://kxstudio.sf.net/ns/lv2ext/programs</li>"
  908. #"<li>http://ll-plugins.nongnu.org/lv2/ext/midimap</li>"
  909. "<li>http://ll-plugins.nongnu.org/lv2/ext/miditype</li>"
  910. "<li>http://nedko.arnaudov.name/lv2/external_ui/</li>"
  911. "</ul>"))
  912. self.l_vst.setText(self.tr("<p>About 85&#37; complete (missing vst bank/presets and some minor stuff)</p>"))
  913. def done(self, r):
  914. QDialog.done(self, r)
  915. self.close()
  916. # Main Window
  917. class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW):
  918. def __init__(self, parent=None):
  919. QMainWindow.__init__(self, parent)
  920. self.setupUi(self)
  921. # -------------------------------------------------------------
  922. # Load Settings
  923. self.settings = QSettings("Cadence", "Carla")
  924. self.settings_db = QSettings("Cadence", "Carla-Database")
  925. self.loadSettings(True)
  926. self.loadRDFs()
  927. self.setStyleSheet("""
  928. QWidget#centralwidget {
  929. background-color: qlineargradient(spread:pad,
  930. x1:0.0, y1:0.0,
  931. x2:0.2, y2:1.0,
  932. stop:0 rgb( 7, 7, 7),
  933. stop:1 rgb(28, 28, 28)
  934. );
  935. }
  936. """)
  937. # -------------------------------------------------------------
  938. # Internal stuff
  939. self.m_engine_started = False
  940. self.m_project_filename = None
  941. self.m_pluginCount = 0
  942. self._nsmAnnounce2str = ""
  943. self._nsmOpen1str = ""
  944. self._nsmOpen2str = ""
  945. self.nsm_server = None
  946. self.nsm_url = None
  947. self.m_plugin_list = []
  948. for x in range(MAX_PLUGINS):
  949. self.m_plugin_list.append(None)
  950. # -------------------------------------------------------------
  951. # Set-up GUI stuff
  952. self.act_engine_start.setEnabled(False)
  953. self.act_engine_stop.setEnabled(False)
  954. self.act_plugin_remove_all.setEnabled(False)
  955. self.resize(self.width(), 0)
  956. # -------------------------------------------------------------
  957. # Connect actions to functions
  958. self.connect(self.act_file_new, SIGNAL("triggered()"), SLOT("slot_file_new()"))
  959. self.connect(self.act_file_open, SIGNAL("triggered()"), SLOT("slot_file_open()"))
  960. self.connect(self.act_file_save, SIGNAL("triggered()"), SLOT("slot_file_save()"))
  961. self.connect(self.act_file_save_as, SIGNAL("triggered()"), SLOT("slot_file_save_as()"))
  962. self.connect(self.act_engine_start, SIGNAL("triggered()"), SLOT("slot_engine_start()"))
  963. self.connect(self.act_engine_stop, SIGNAL("triggered()"), SLOT("slot_engine_stop()"))
  964. self.connect(self.act_plugin_add, SIGNAL("triggered()"), SLOT("slot_plugin_add()"))
  965. self.connect(self.act_plugin_remove_all, SIGNAL("triggered()"), SLOT("slot_remove_all()"))
  966. self.connect(self.act_settings_configure, SIGNAL("triggered()"), SLOT("slot_configureCarla()"))
  967. self.connect(self.act_help_about, SIGNAL("triggered()"), SLOT("slot_aboutCarla()"))
  968. self.connect(self.act_help_about_qt, SIGNAL("triggered()"), app, SLOT("aboutQt()"))
  969. self.connect(self, SIGNAL("SIGUSR1()"), SLOT("slot_handleSIGUSR1()"))
  970. self.connect(self, SIGNAL("DebugCallback(int, int, int, double)"), SLOT("slot_handleDebugCallback(int, int, int, double)"))
  971. self.connect(self, SIGNAL("ParameterCallback(int, int, double)"), SLOT("slot_handleParameterCallback(int, int, double)"))
  972. self.connect(self, SIGNAL("ProgramCallback(int, int)"), SLOT("slot_handleProgramCallback(int, int)"))
  973. self.connect(self, SIGNAL("MidiProgramCallback(int, int)"), SLOT("slot_handleMidiProgramCallback(int, int)"))
  974. self.connect(self, SIGNAL("NoteOnCallback(int, int, int, int)"), SLOT("slot_handleNoteOnCallback(int, int, int, int)"))
  975. self.connect(self, SIGNAL("NoteOffCallback(int, int, int)"), SLOT("slot_handleNoteOffCallback(int, int, int)"))
  976. self.connect(self, SIGNAL("ShowGuiCallback(int, int)"), SLOT("slot_handleShowGuiCallback(int, int)"))
  977. self.connect(self, SIGNAL("ResizeGuiCallback(int, int, int)"), SLOT("slot_handleResizeGuiCallback(int, int, int)"))
  978. self.connect(self, SIGNAL("UpdateCallback(int)"), SLOT("slot_handleUpdateCallback(int)"))
  979. self.connect(self, SIGNAL("ReloadInfoCallback(int)"), SLOT("slot_handleReloadInfoCallback(int)"))
  980. self.connect(self, SIGNAL("ReloadParametersCallback(int)"), SLOT("slot_handleReloadParametersCallback(int)"))
  981. self.connect(self, SIGNAL("ReloadProgramsCallback(int)"), SLOT("slot_handleReloadProgramsCallback(int)"))
  982. self.connect(self, SIGNAL("ReloadAllCallback(int)"), SLOT("slot_handleReloadAllCallback(int)"))
  983. self.connect(self, SIGNAL("NSM_AnnounceCallback()"), SLOT("slot_handleNSM_AnnounceCallback()"))
  984. self.connect(self, SIGNAL("NSM_Open1Callback()"), SLOT("slot_handleNSM_Open1Callback()"))
  985. self.connect(self, SIGNAL("NSM_Open2Callback()"), SLOT("slot_handleNSM_Open2Callback()"))
  986. self.connect(self, SIGNAL("NSM_SaveCallback()"), SLOT("slot_handleNSM_SaveCallback()"))
  987. self.connect(self, SIGNAL("QuitCallback()"), SLOT("slot_handleQuitCallback()"))
  988. self.TIMER_GUI_STUFF = self.startTimer(self.m_savedSettings["Main/RefreshInterval"]) # Peaks
  989. self.TIMER_GUI_STUFF2 = self.startTimer(self.m_savedSettings["Main/RefreshInterval"] * 2) # LEDs and edit dialog
  990. NSM_URL = os.getenv("NSM_URL")
  991. if NSM_URL:
  992. Carla.Host.nsm_announce(NSM_URL, os.getpid())
  993. else:
  994. QTimer.singleShot(0, self, SLOT("slot_engine_start()"))
  995. def loadProjectLater(self):
  996. QTimer.singleShot(0, self.load_project)
  997. def startEngine(self, clientName = "Carla"):
  998. # ---------------------------------------------
  999. # engine
  1000. Carla.processMode = self.settings.value("Engine/ProcessMode", PROCESS_MODE_MULTIPLE_CLIENTS, type=int)
  1001. Carla.maxParameters = self.settings.value("Engine/MaxParameters", MAX_PARAMETERS, type=int)
  1002. processHighPrecision = self.settings.value("Engine/ProcessHighPrecision", False, type=bool)
  1003. preferredBufferSize = self.settings.value("Engine/PreferredBufferSize", 512, type=int)
  1004. preferredSampleRate = self.settings.value("Engine/PreferredSampleRate", 44100, type=int)
  1005. forceStereo = self.settings.value("Engine/ForceStereo", False, type=bool)
  1006. useDssiVstChunks = self.settings.value("Engine/UseDssiVstChunks", False, type=bool)
  1007. preferUiBridges = self.settings.value("Engine/PreferUiBridges", True, type=bool)
  1008. oscUiTimeout = self.settings.value("Engine/OscUiTimeout", 40, type=int)
  1009. if Carla.processMode == PROCESS_MODE_CONTINUOUS_RACK:
  1010. forceStereo = True
  1011. elif Carla.processMode == PROCESS_MODE_MULTIPLE_CLIENTS and os.getenv("LADISH_APP_NAME"):
  1012. print("LADISH detected but using multiple clients (not allowed), forcing single client now")
  1013. Carla.processMode = PROCESS_MODE_SINGLE_CLIENT
  1014. Carla.Host.set_option(OPTION_PROCESS_MODE, Carla.processMode, "")
  1015. Carla.Host.set_option(OPTION_PROCESS_HIGH_PRECISION, processHighPrecision, "")
  1016. Carla.Host.set_option(OPTION_MAX_PARAMETERS, Carla.maxParameters, "")
  1017. Carla.Host.set_option(OPTION_PREFERRED_BUFFER_SIZE, preferredBufferSize, "")
  1018. Carla.Host.set_option(OPTION_PREFERRED_SAMPLE_RATE, preferredSampleRate, "")
  1019. Carla.Host.set_option(OPTION_FORCE_STEREO, forceStereo, "")
  1020. Carla.Host.set_option(OPTION_USE_DSSI_VST_CHUNKS, useDssiVstChunks, "")
  1021. Carla.Host.set_option(OPTION_PREFER_UI_BRIDGES, preferUiBridges, "")
  1022. Carla.Host.set_option(OPTION_OSC_UI_TIMEOUT, oscUiTimeout, "")
  1023. # ---------------------------------------------
  1024. # bridge paths
  1025. if carla_bridge_posix32:
  1026. Carla.Host.set_option(OPTION_PATH_BRIDGE_POSIX32, 0, carla_bridge_posix32)
  1027. if carla_bridge_posix64:
  1028. Carla.Host.set_option(OPTION_PATH_BRIDGE_POSIX64, 0, carla_bridge_posix64)
  1029. if carla_bridge_win32:
  1030. Carla.Host.set_option(OPTION_PATH_BRIDGE_WIN32, 0, carla_bridge_win32)
  1031. if carla_bridge_win64:
  1032. Carla.Host.set_option(OPTION_PATH_BRIDGE_WIN64, 0, carla_bridge_win64)
  1033. if carla_bridge_lv2_gtk2:
  1034. Carla.Host.set_option(OPTION_PATH_BRIDGE_LV2_GTK2, 0, carla_bridge_lv2_gtk2)
  1035. if carla_bridge_lv2_qt4:
  1036. Carla.Host.set_option(OPTION_PATH_BRIDGE_LV2_QT4, 0, carla_bridge_lv2_qt4)
  1037. if carla_bridge_lv2_x11:
  1038. Carla.Host.set_option(OPTION_PATH_BRIDGE_LV2_X11, 0, carla_bridge_lv2_x11)
  1039. if carla_bridge_vst_x11:
  1040. Carla.Host.set_option(OPTION_PATH_BRIDGE_VST_X11, 0, carla_bridge_vst_x11)
  1041. # ---------------------------------------------
  1042. # start
  1043. audioDriver = self.settings.value("Engine/AudioDriver", "JACK", type=str)
  1044. if not Carla.Host.engine_init(audioDriver, clientName):
  1045. self.act_engine_start.setEnabled(True)
  1046. self.act_engine_stop.setEnabled(False)
  1047. QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s', possible reasons: %s" % (audioDriver, cString(Carla.Host.get_last_error()))))
  1048. return
  1049. self.m_engine_started = True
  1050. def stopEngine(self):
  1051. if self.m_pluginCount > 0:
  1052. ask = QMessageBox.question(self, self.tr("Warning"), self.tr("There are still some plugins loaded, you need to remove them to stop the engine.\n"
  1053. "Do you want to do this now?"),
  1054. QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
  1055. if ask == QMessageBox.Yes:
  1056. self.slot_remove_all()
  1057. else:
  1058. return
  1059. if Carla.Host.is_engine_running() and not Carla.Host.engine_close():
  1060. print(cString(Carla.Host.get_last_error()))
  1061. self.m_engine_started = False
  1062. @pyqtSlot()
  1063. def slot_engine_start(self):
  1064. self.startEngine()
  1065. check = Carla.Host.is_engine_running()
  1066. self.act_file_open.setEnabled(check)
  1067. self.act_engine_start.setEnabled(not check)
  1068. self.act_engine_stop.setEnabled(check)
  1069. @pyqtSlot()
  1070. def slot_engine_stop(self):
  1071. self.stopEngine()
  1072. check = Carla.Host.is_engine_running()
  1073. self.act_file_open.setEnabled(check)
  1074. self.act_engine_start.setEnabled(not check)
  1075. self.act_engine_stop.setEnabled(check)
  1076. @pyqtSlot()
  1077. def slot_handleSIGUSR1(self):
  1078. print("Got SIGUSR1 -> Saving project now")
  1079. QTimer.singleShot(0, self, SLOT("slot_file_save()"))
  1080. @pyqtSlot(int, int, int, float)
  1081. def slot_handleDebugCallback(self, plugin_id, value1, value2, value3):
  1082. print("DEBUG :: %i, %i, %i, %f)" % (plugin_id, value1, value2, value3))
  1083. @pyqtSlot(int, int, float)
  1084. def slot_handleParameterCallback(self, pluginId, parameterId, value):
  1085. pwidget = self.m_plugin_list[pluginId]
  1086. if pwidget:
  1087. pwidget.m_parameterIconTimer = ICON_STATE_ON
  1088. if parameterId == PARAMETER_ACTIVE:
  1089. pwidget.set_active((value > 0.0), True, False)
  1090. elif parameterId == PARAMETER_DRYWET:
  1091. pwidget.set_drywet(value * 1000, True, False)
  1092. elif parameterId == PARAMETER_VOLUME:
  1093. pwidget.set_volume(value * 1000, True, False)
  1094. elif parameterId == PARAMETER_BALANCE_LEFT:
  1095. pwidget.set_balance_left(value * 1000, True, False)
  1096. elif parameterId == PARAMETER_BALANCE_RIGHT:
  1097. pwidget.set_balance_right(value * 1000, True, False)
  1098. elif parameterId >= 0:
  1099. pwidget.edit_dialog.set_parameter_to_update(parameterId)
  1100. @pyqtSlot(int, int)
  1101. def slot_handleProgramCallback(self, plugin_id, program_id):
  1102. pwidget = self.m_plugin_list[plugin_id]
  1103. if pwidget:
  1104. pwidget.edit_dialog.set_program(program_id)
  1105. @pyqtSlot(int, int)
  1106. def slot_handleMidiProgramCallback(self, plugin_id, midi_program_id):
  1107. pwidget = self.m_plugin_list[plugin_id]
  1108. if pwidget:
  1109. pwidget.edit_dialog.set_midi_program(midi_program_id)
  1110. @pyqtSlot(int, int, int, int)
  1111. def slot_handleNoteOnCallback(self, plugin_id, channel, note, velo):
  1112. pwidget = self.m_plugin_list[plugin_id]
  1113. if pwidget:
  1114. pwidget.edit_dialog.keyboard.sendNoteOn(note, False)
  1115. @pyqtSlot(int, int, int)
  1116. def slot_handleNoteOffCallback(self, plugin_id, channel, note):
  1117. pwidget = self.m_plugin_list[plugin_id]
  1118. if pwidget:
  1119. pwidget.edit_dialog.keyboard.sendNoteOff(note, False)
  1120. @pyqtSlot(int, int)
  1121. def slot_handleShowGuiCallback(self, plugin_id, show):
  1122. pwidget = self.m_plugin_list[plugin_id]
  1123. if pwidget:
  1124. if show == 0:
  1125. pwidget.b_gui.setChecked(False)
  1126. pwidget.b_gui.setEnabled(True)
  1127. elif show == 1:
  1128. pwidget.b_gui.setChecked(True)
  1129. pwidget.b_gui.setEnabled(True)
  1130. elif show == -1:
  1131. pwidget.b_gui.setChecked(False)
  1132. pwidget.b_gui.setEnabled(False)
  1133. @pyqtSlot(int, int, int)
  1134. def slot_handleResizeGuiCallback(self, plugin_id, width, height):
  1135. pwidget = self.m_plugin_list[plugin_id]
  1136. if pwidget:
  1137. gui_dialog = pwidget.gui_dialog
  1138. if gui_dialog:
  1139. gui_dialog.setNewSize(width, height)
  1140. @pyqtSlot(int)
  1141. def slot_handleUpdateCallback(self, plugin_id):
  1142. pwidget = self.m_plugin_list[plugin_id]
  1143. if pwidget:
  1144. pwidget.edit_dialog.do_update()
  1145. @pyqtSlot(int)
  1146. def slot_handleReloadInfoCallback(self, plugin_id):
  1147. pwidget = self.m_plugin_list[plugin_id]
  1148. if pwidget:
  1149. pwidget.edit_dialog.do_reload_info()
  1150. @pyqtSlot(int)
  1151. def slot_handleReloadParametersCallback(self, plugin_id):
  1152. pwidget = self.m_plugin_list[plugin_id]
  1153. if pwidget:
  1154. pwidget.edit_dialog.do_reload_parameters()
  1155. @pyqtSlot(int)
  1156. def slot_handleReloadProgramsCallback(self, plugin_id):
  1157. pwidget = self.m_plugin_list[plugin_id]
  1158. if pwidget:
  1159. pwidget.edit_dialog.do_reload_programs()
  1160. @pyqtSlot(int)
  1161. def slot_handleReloadAllCallback(self, plugin_id):
  1162. pwidget = self.m_plugin_list[plugin_id]
  1163. if pwidget:
  1164. pwidget.edit_dialog.do_reload_all()
  1165. @pyqtSlot()
  1166. def slot_handleNSM_AnnounceCallback(self):
  1167. smName = self._nsmAnnounce2str
  1168. self.act_file_new.setEnabled(False)
  1169. self.act_file_open.setEnabled(False)
  1170. self.act_file_save_as.setEnabled(False)
  1171. self.setWindowTitle("Carla (%s)" % smName)
  1172. @pyqtSlot()
  1173. def slot_handleNSM_Open1Callback(self):
  1174. clientId = self._nsmOpen1str
  1175. # remove all previous plugins
  1176. self.slot_remove_all()
  1177. # restart engine
  1178. if Carla.Host.is_engine_running():
  1179. self.stopEngine()
  1180. self.startEngine(clientId)
  1181. @pyqtSlot()
  1182. def slot_handleNSM_Open2Callback(self):
  1183. projectPath = self._nsmOpen2str
  1184. self.m_project_filename = projectPath
  1185. if os.path.exists(self.m_project_filename):
  1186. self.load_project()
  1187. else:
  1188. self.save_project()
  1189. self.setWindowTitle("Carla - %s" % os.path.basename(self.m_project_filename))
  1190. Carla.Host.nsm_reply_open()
  1191. @pyqtSlot()
  1192. def slot_handleNSM_SaveCallback(self):
  1193. self.save_project()
  1194. Carla.Host.nsm_reply_save()
  1195. @pyqtSlot()
  1196. def slot_handleQuitCallback(self):
  1197. CustomMessageBox(self, QMessageBox.Warning, self.tr("Warning"),
  1198. self.tr("JACK has been stopped or crashed.\nPlease start JACK and restart Carla"),
  1199. self.tr("You may want to save your session now..."), QMessageBox.Ok, QMessageBox.Ok)
  1200. def add_plugin(self, btype, ptype, filename, name, label, extra_stuff, activate):
  1201. if not self.m_engine_started:
  1202. if activate:
  1203. QMessageBox.warning(self, self.tr("Warning"), self.tr("Cannot add new plugins while engine is stopped"))
  1204. return -1
  1205. new_plugin_id = Carla.Host.add_plugin(btype, ptype, filename, name, label, extra_stuff)
  1206. if new_plugin_id < 0:
  1207. CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to load plugin"), cString(Carla.Host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)
  1208. return -1
  1209. else:
  1210. pwidget = PluginWidget(self, new_plugin_id)
  1211. self.w_plugins.layout().addWidget(pwidget)
  1212. self.m_plugin_list[new_plugin_id] = pwidget
  1213. self.act_plugin_remove_all.setEnabled(True)
  1214. pwidget.peak_in.setRefreshRate(self.m_savedSettings["Main/RefreshInterval"])
  1215. pwidget.peak_out.setRefreshRate(self.m_savedSettings["Main/RefreshInterval"])
  1216. if activate:
  1217. pwidget.set_active(True, True, True)
  1218. self.m_pluginCount += 1
  1219. return new_plugin_id
  1220. def remove_plugin(self, plugin_id, showError):
  1221. pwidget = self.m_plugin_list[plugin_id]
  1222. pwidget.edit_dialog.close()
  1223. if pwidget.gui_dialog:
  1224. pwidget.gui_dialog.close()
  1225. if Carla.Host.remove_plugin(plugin_id):
  1226. pwidget.close()
  1227. pwidget.deleteLater()
  1228. self.w_plugins.layout().removeWidget(pwidget)
  1229. self.m_plugin_list[plugin_id] = None
  1230. self.m_pluginCount -= 1
  1231. elif showError:
  1232. CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to remove plugin"), cString(Carla.Host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)
  1233. # push all plugins 1 slot if rack mode
  1234. if Carla.processMode == PROCESS_MODE_CONTINUOUS_RACK:
  1235. for i in range(MAX_PLUGINS-1):
  1236. if i < plugin_id: continue
  1237. self.m_plugin_list[i] = self.m_plugin_list[i+1]
  1238. if self.m_plugin_list[i]:
  1239. self.m_plugin_list[i].setId(i)
  1240. self.m_plugin_list[MAX_PLUGINS-1] = None
  1241. # check if there are still plugins
  1242. for i in range(MAX_PLUGINS):
  1243. if self.m_plugin_list[i]: break
  1244. else:
  1245. self.act_plugin_remove_all.setEnabled(False)
  1246. def get_extra_stuff(self, plugin):
  1247. ptype = plugin['type']
  1248. if ptype == PLUGIN_LADSPA:
  1249. unique_id = plugin['unique_id']
  1250. for rdf_item in self.ladspa_rdf_list:
  1251. if rdf_item.UniqueID == unique_id:
  1252. return pointer(rdf_item)
  1253. elif ptype == PLUGIN_DSSI:
  1254. if plugin['hints'] & PLUGIN_HAS_GUI:
  1255. gui = findDSSIGUI(plugin['binary'], plugin['name'], plugin['label'])
  1256. if gui:
  1257. return gui.encode("utf-8")
  1258. return c_nullptr
  1259. def save_project(self):
  1260. content = ("<?xml version='1.0' encoding='UTF-8'?>\n"
  1261. "<!DOCTYPE CARLA-PROJECT>\n"
  1262. "<CARLA-PROJECT VERSION='%s'>\n") % (VERSION)
  1263. first_plugin = True
  1264. for pwidget in self.m_plugin_list:
  1265. if pwidget:
  1266. if not first_plugin:
  1267. content += "\n"
  1268. real_plugin_name = cString(Carla.Host.get_real_plugin_name(pwidget.m_pluginId))
  1269. if real_plugin_name:
  1270. content += " <!-- %s -->\n" % xmlSafeString(real_plugin_name, True)
  1271. content += " <Plugin>\n"
  1272. content += pwidget.getSaveXMLContent()
  1273. content += " </Plugin>\n"
  1274. first_plugin = False
  1275. content += "</CARLA-PROJECT>\n"
  1276. try:
  1277. fd = uopen(self.m_project_filename, "w")
  1278. fd.write(content)
  1279. fd.close()
  1280. except:
  1281. QMessageBox.critical(self, self.tr("Error"), self.tr("Failed to save project file"))
  1282. def load_project(self):
  1283. try:
  1284. fd = uopen(self.m_project_filename, "r")
  1285. projectRead = fd.read()
  1286. fd.close()
  1287. except:
  1288. projectRead = None
  1289. if not projectRead:
  1290. QMessageBox.critical(self, self.tr("Error"), self.tr("Failed to load project file"))
  1291. return
  1292. xml = QDomDocument()
  1293. xml.setContent(projectRead.encode("utf-8"))
  1294. xml_node = xml.documentElement()
  1295. if xml_node.tagName() != "CARLA-PROJECT":
  1296. QMessageBox.critical(self, self.tr("Error"), self.tr("Not a valid Carla project file"))
  1297. return
  1298. x_ladspa_plugins = None
  1299. x_dssi_plugins = None
  1300. x_lv2_plugins = None
  1301. x_vst_plugins = None
  1302. x_gig_plugins = None
  1303. x_sf2_plugins = None
  1304. x_sfz_plugins = None
  1305. x_failed_plugins = []
  1306. x_save_state_dicts = []
  1307. node = xml_node.firstChild()
  1308. while not node.isNull():
  1309. if node.toElement().tagName() == "Plugin":
  1310. x_save_state_dict = getSaveStateDictFromXML(node)
  1311. x_save_state_dicts.append(x_save_state_dict)
  1312. node = node.nextSibling()
  1313. for x_save_state_dict in x_save_state_dicts:
  1314. ptype = x_save_state_dict['Type']
  1315. label = x_save_state_dict['Label']
  1316. binary = x_save_state_dict['Binary']
  1317. binaryS = os.path.basename(binary)
  1318. unique_id = x_save_state_dict['UniqueID']
  1319. if ptype == "LADSPA":
  1320. if not x_ladspa_plugins:
  1321. x_ladspa_plugins = []
  1322. x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_native", []))
  1323. x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_posix32", []))
  1324. x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_posix64", []))
  1325. x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_win32", []))
  1326. x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_win64", []))
  1327. x_plugins = x_ladspa_plugins
  1328. elif ptype == "DSSI":
  1329. if not x_dssi_plugins:
  1330. x_dssi_plugins = []
  1331. x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_native", []))
  1332. x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_posix32", []))
  1333. x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_posix64", []))
  1334. x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_win32", []))
  1335. x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_win64", []))
  1336. x_plugins = x_dssi_plugins
  1337. elif ptype == "LV2":
  1338. if not x_lv2_plugins:
  1339. x_lv2_plugins = []
  1340. x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_native", []))
  1341. x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_posix32", []))
  1342. x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_posix64", []))
  1343. x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_win32", []))
  1344. x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_win64", []))
  1345. x_plugins = x_lv2_plugins
  1346. elif ptype == "VST":
  1347. if not x_vst_plugins:
  1348. x_vst_plugins = []
  1349. x_vst_plugins += toList(self.settings_db.value("Plugins/VST_native", []))
  1350. x_vst_plugins += toList(self.settings_db.value("Plugins/VST_posix32", []))
  1351. x_vst_plugins += toList(self.settings_db.value("Plugins/VST_posix64", []))
  1352. x_vst_plugins += toList(self.settings_db.value("Plugins/VST_win32", []))
  1353. x_vst_plugins += toList(self.settings_db.value("Plugins/VST_win64", []))
  1354. x_plugins = x_vst_plugins
  1355. elif ptype == "GIG":
  1356. if not x_gig_plugins: x_gig_plugins = toList(self.settings_db.value("Plugins/GIG", []))
  1357. x_plugins = x_gig_plugins
  1358. elif ptype == "SF2":
  1359. if not x_sf2_plugins: x_sf2_plugins = toList(self.settings_db.value("Plugins/SF2", []))
  1360. x_plugins = x_sf2_plugins
  1361. elif ptype == "SFZ":
  1362. if not x_sfz_plugins: x_sfz_plugins = toList(self.settings_db.value("Plugins/SFZ", []))
  1363. x_plugins = x_sfz_plugins
  1364. else:
  1365. print("load_project() - ptype '%s' not recognized", ptype)
  1366. x_failed_plugins.append(x_save_state_dict['Name'])
  1367. continue
  1368. # Try UniqueID -> Label -> Binary (full) -> Binary (short)
  1369. plugin_ulB = None
  1370. plugin_ulb = None
  1371. plugin_ul = None
  1372. plugin_uB = None
  1373. plugin_ub = None
  1374. plugin_lB = None
  1375. plugin_lb = None
  1376. plugin_u = None
  1377. plugin_l = None
  1378. plugin_B = None
  1379. for _plugins in x_plugins:
  1380. for x_plugin in _plugins:
  1381. if unique_id == x_plugin['unique_id'] and label == x_plugin['label'] and binary == x_plugin['binary']:
  1382. plugin_ulB = x_plugin
  1383. break
  1384. elif unique_id == x_plugin['unique_id'] and label == x_plugin['label'] and binaryS == os.path.basename(x_plugin['binary']):
  1385. plugin_ulb = x_plugin
  1386. elif unique_id == x_plugin['unique_id'] and label == x_plugin['label']:
  1387. plugin_ul = x_plugin
  1388. elif unique_id == x_plugin['unique_id'] and binary == x_plugin['binary']:
  1389. plugin_uB = x_plugin
  1390. elif unique_id == x_plugin['unique_id'] and binaryS == os.path.basename(x_plugin['binary']):
  1391. plugin_ub = x_plugin
  1392. elif label == x_plugin['label'] and binary == x_plugin['binary']:
  1393. plugin_lB = x_plugin
  1394. elif label == x_plugin['label'] and binaryS == os.path.basename(x_plugin['binary']):
  1395. plugin_lb = x_plugin
  1396. elif unique_id == x_plugin['unique_id']:
  1397. plugin_u = x_plugin
  1398. elif label == x_plugin['label']:
  1399. plugin_l = x_plugin
  1400. elif binary == x_plugin['binary']:
  1401. plugin_B = x_plugin
  1402. # LADSPA uses UniqueID or binary+label
  1403. if ptype == "LADSPA":
  1404. plugin_l = None
  1405. plugin_B = None
  1406. # DSSI uses binary+label (UniqueID ignored)
  1407. elif ptype == "DSSI":
  1408. plugin_ul = None
  1409. plugin_uB = None
  1410. plugin_ub = None
  1411. plugin_u = None
  1412. plugin_l = None
  1413. plugin_B = None
  1414. # LV2 uses URIs (label in this case)
  1415. elif ptype == "LV2":
  1416. plugin_uB = None
  1417. plugin_ub = None
  1418. plugin_u = None
  1419. plugin_B = None
  1420. # VST uses UniqueID
  1421. elif ptype == "VST":
  1422. plugin_lB = None
  1423. plugin_lb = None
  1424. plugin_l = None
  1425. plugin_B = None
  1426. # Sound Kits use binaries
  1427. elif ptype in ("GIG", "SF2", "SFZ"):
  1428. plugin_ul = None
  1429. plugin_u = None
  1430. plugin_l = None
  1431. if (plugin_ulB):
  1432. plugin = plugin_ulB
  1433. elif (plugin_ulb):
  1434. plugin = plugin_ulb
  1435. elif (plugin_ul):
  1436. plugin = plugin_ul
  1437. elif (plugin_uB):
  1438. plugin = plugin_uB
  1439. elif (plugin_ub):
  1440. plugin = plugin_ub
  1441. elif (plugin_lB):
  1442. plugin = plugin_lB
  1443. elif (plugin_lb):
  1444. plugin = plugin_lb
  1445. elif (plugin_u):
  1446. plugin = plugin_u
  1447. elif (plugin_l):
  1448. plugin = plugin_l
  1449. elif (plugin_B):
  1450. plugin = plugin_B
  1451. else:
  1452. plugin = None
  1453. if plugin:
  1454. btype = plugin['build']
  1455. ptype = plugin['type']
  1456. filename = plugin['binary']
  1457. name = x_save_state_dict['Name']
  1458. label = plugin['label']
  1459. extra_stuff = self.get_extra_stuff(plugin)
  1460. new_plugin_id = self.add_plugin(btype, ptype, filename, name, label, extra_stuff, False)
  1461. if new_plugin_id >= 0:
  1462. pwidget = self.m_plugin_list[new_plugin_id]
  1463. pwidget.loadStateDict(x_save_state_dict)
  1464. else:
  1465. x_failed_plugins.append(x_save_state_dict['Name'])
  1466. else:
  1467. x_failed_plugins.append(x_save_state_dict['Name'])
  1468. if len(x_failed_plugins) > 0:
  1469. text = self.tr("The following plugins were not found or failed to initialize:\n")
  1470. for plugin in x_failed_plugins:
  1471. text += " - %s\n" % plugin
  1472. self.statusBar().showMessage("State file loaded with errors")
  1473. QMessageBox.critical(self, self.tr("Error"), text)
  1474. else:
  1475. self.statusBar().showMessage("State file loaded sucessfully!")
  1476. def loadRDFs(self):
  1477. # Save RDF info for later
  1478. if haveLRDF:
  1479. SettingsDir = os.path.join(HOME, ".config", "Cadence")
  1480. fr_ladspa_file = os.path.join(SettingsDir, "ladspa_rdf.db")
  1481. if os.path.exists(fr_ladspa_file):
  1482. fr_ladspa = open(fr_ladspa_file, 'r')
  1483. try:
  1484. self.ladspa_rdf_list = ladspa_rdf.get_c_ladspa_rdfs(json.load(fr_ladspa))
  1485. except:
  1486. self.ladspa_rdf_list = []
  1487. fr_ladspa.close()
  1488. return
  1489. self.ladspa_rdf_list = []
  1490. @pyqtSlot()
  1491. def slot_file_new(self):
  1492. self.slot_remove_all()
  1493. self.m_project_filename = None
  1494. self.setWindowTitle("Carla")
  1495. @pyqtSlot()
  1496. def slot_file_open(self):
  1497. file_filter = self.tr("Carla Project File (*.carxp)")
  1498. filename = QFileDialog.getOpenFileName(self, self.tr("Open Carla Project File"),
  1499. self.m_savedSettings["Main/DefaultProjectFolder"], filter=file_filter)
  1500. if filename:
  1501. self.m_project_filename = filename
  1502. self.slot_remove_all()
  1503. self.load_project()
  1504. self.setWindowTitle("Carla - %s" % os.path.basename(self.m_project_filename))
  1505. @pyqtSlot()
  1506. def slot_file_save(self, saveAs=False):
  1507. if self.m_project_filename == None or saveAs:
  1508. file_filter = self.tr("Carla Project File (*.carxp)")
  1509. filename = QFileDialog.getSaveFileName(self, self.tr("Save Carla Project File"),
  1510. self.m_savedSettings["Main/DefaultProjectFolder"], filter=file_filter)
  1511. if filename:
  1512. self.m_project_filename = filename
  1513. self.save_project()
  1514. self.setWindowTitle("Carla - %s" % os.path.basename(self.m_project_filename))
  1515. else:
  1516. self.save_project()
  1517. @pyqtSlot()
  1518. def slot_file_save_as(self):
  1519. self.slot_file_save(True)
  1520. @pyqtSlot()
  1521. def slot_plugin_add(self):
  1522. dialog = PluginDatabaseW(self)
  1523. if dialog.exec_():
  1524. btype = dialog.ret_plugin['build']
  1525. ptype = dialog.ret_plugin['type']
  1526. filename = dialog.ret_plugin['binary']
  1527. label = dialog.ret_plugin['label']
  1528. extra_stuff = self.get_extra_stuff(dialog.ret_plugin)
  1529. self.add_plugin(btype, ptype, filename, None, label, extra_stuff, True)
  1530. @pyqtSlot()
  1531. def slot_remove_all(self):
  1532. h = 0
  1533. for i in range(MAX_PLUGINS):
  1534. pwidget = self.m_plugin_list[i]
  1535. if not pwidget:
  1536. continue
  1537. pwidget.setId(i-h)
  1538. pwidget.edit_dialog.close()
  1539. if pwidget.gui_dialog:
  1540. pwidget.gui_dialog.close()
  1541. if Carla.Host.remove_plugin(i-h):
  1542. pwidget.close()
  1543. pwidget.deleteLater()
  1544. self.w_plugins.layout().removeWidget(pwidget)
  1545. self.m_plugin_list[i] = None
  1546. if Carla.processMode == PROCESS_MODE_CONTINUOUS_RACK:
  1547. h += 1
  1548. self.m_pluginCount = 0
  1549. self.act_plugin_remove_all.setEnabled(False)
  1550. @pyqtSlot()
  1551. def slot_configureCarla(self):
  1552. dialog = SettingsW(self, "carla")
  1553. if dialog.exec_():
  1554. self.loadSettings(False)
  1555. for pwidget in self.m_plugin_list:
  1556. if pwidget:
  1557. pwidget.peak_in.setRefreshRate(self.m_savedSettings["Main/RefreshInterval"])
  1558. pwidget.peak_out.setRefreshRate(self.m_savedSettings["Main/RefreshInterval"])
  1559. @pyqtSlot()
  1560. def slot_aboutCarla(self):
  1561. CarlaAboutW(self).exec_()
  1562. def saveSettings(self):
  1563. self.settings.setValue("Geometry", self.saveGeometry())
  1564. self.settings.setValue("ShowToolbar", self.toolBar.isVisible())
  1565. def loadSettings(self, geometry):
  1566. if geometry:
  1567. self.restoreGeometry(self.settings.value("Geometry", ""))
  1568. show_toolbar = self.settings.value("ShowToolbar", True, type=bool)
  1569. self.act_settings_show_toolbar.setChecked(show_toolbar)
  1570. self.toolBar.setVisible(show_toolbar)
  1571. self.m_savedSettings = {
  1572. "Main/DefaultProjectFolder": self.settings.value("Main/DefaultProjectFolder", DEFAULT_PROJECT_FOLDER, type=str),
  1573. "Main/RefreshInterval": self.settings.value("Main/RefreshInterval", 120, type=int)
  1574. }
  1575. # ---------------------------------------------
  1576. # plugin checks
  1577. disableChecks = self.settings.value("Engine/DisableChecks", bool(not WINDOWS), type=bool)
  1578. if disableChecks:
  1579. os.environ["CARLA_DISCOVERY_NO_PROCESSING_CHECKS"] = "true"
  1580. else:
  1581. try:
  1582. os.environ.pop("CARLA_DISCOVERY_NO_PROCESSING_CHECKS")
  1583. except:
  1584. pass
  1585. # ---------------------------------------------
  1586. # plugin paths
  1587. global LADSPA_PATH, DSSI_PATH, LV2_PATH, VST_PATH, GIG_PATH, SF2_PATH, SFZ_PATH
  1588. LADSPA_PATH = toList(self.settings.value("Paths/LADSPA", LADSPA_PATH))
  1589. DSSI_PATH = toList(self.settings.value("Paths/DSSI", DSSI_PATH))
  1590. LV2_PATH = toList(self.settings.value("Paths/LV2", LV2_PATH))
  1591. VST_PATH = toList(self.settings.value("Paths/VST", VST_PATH))
  1592. GIG_PATH = toList(self.settings.value("Paths/GIG", GIG_PATH))
  1593. SF2_PATH = toList(self.settings.value("Paths/SF2", SF2_PATH))
  1594. SFZ_PATH = toList(self.settings.value("Paths/SFZ", SFZ_PATH))
  1595. Carla.Host.set_option(OPTION_PATH_LADSPA, 0, splitter.join(LADSPA_PATH))
  1596. Carla.Host.set_option(OPTION_PATH_DSSI, 0, splitter.join(DSSI_PATH))
  1597. Carla.Host.set_option(OPTION_PATH_LV2, 0, splitter.join(LV2_PATH))
  1598. Carla.Host.set_option(OPTION_PATH_VST, 0, splitter.join(VST_PATH))
  1599. Carla.Host.set_option(OPTION_PATH_GIG, 0, splitter.join(GIG_PATH))
  1600. Carla.Host.set_option(OPTION_PATH_SF2, 0, splitter.join(SF2_PATH))
  1601. Carla.Host.set_option(OPTION_PATH_SFZ, 0, splitter.join(SFZ_PATH))
  1602. def timerEvent(self, event):
  1603. if event.timerId() == self.TIMER_GUI_STUFF:
  1604. for pwidget in self.m_plugin_list:
  1605. if pwidget: pwidget.check_gui_stuff()
  1606. if self.m_engine_started and self.m_pluginCount > 0:
  1607. Carla.Host.idle_guis()
  1608. elif event.timerId() == self.TIMER_GUI_STUFF2:
  1609. for pwidget in self.m_plugin_list:
  1610. if pwidget: pwidget.check_gui_stuff2()
  1611. QMainWindow.timerEvent(self, event)
  1612. def closeEvent(self, event):
  1613. if self.nsm_server:
  1614. self.nsm_server.stop()
  1615. self.saveSettings()
  1616. self.slot_remove_all()
  1617. QMainWindow.closeEvent(self, event)
  1618. # ------------------------------------------------------------------------------------------------
  1619. def callback_function(ptr, action, pluginId, value1, value2, value3):
  1620. if pluginId< 0 or pluginId >= MAX_PLUGINS or not Carla.gui:
  1621. return
  1622. if action == CALLBACK_DEBUG:
  1623. Carla.gui.emit(SIGNAL("DebugCallback(int, int, int, double)"), pluginId, value1, value2, value3)
  1624. elif action == CALLBACK_PARAMETER_VALUE_CHANGED:
  1625. Carla.gui.emit(SIGNAL("ParameterCallback(int, int, double)"), pluginId, value1, value3)
  1626. # TODO param midi callbacks
  1627. elif action == CALLBACK_PROGRAM_CHANGED:
  1628. Carla.gui.emit(SIGNAL("ProgramCallback(int, int)"), pluginId, value1)
  1629. elif action == CALLBACK_MIDI_PROGRAM_CHANGED:
  1630. Carla.gui.emit(SIGNAL("MidiProgramCallback(int, int)"), pluginId, value1)
  1631. elif action == CALLBACK_NOTE_ON:
  1632. Carla.gui.emit(SIGNAL("NoteOnCallback(int, int, int, int)"), pluginId, value1, value2, value3)
  1633. elif action == CALLBACK_NOTE_OFF:
  1634. Carla.gui.emit(SIGNAL("NoteOffCallback(int, int, int)"), pluginId, value1, value2)
  1635. elif action == CALLBACK_SHOW_GUI:
  1636. Carla.gui.emit(SIGNAL("ShowGuiCallback(int, int)"), pluginId, value1)
  1637. elif action == CALLBACK_RESIZE_GUI:
  1638. Carla.gui.emit(SIGNAL("ResizeGuiCallback(int, int, int)"), pluginId, value1, value2)
  1639. elif action == CALLBACK_UPDATE:
  1640. Carla.gui.emit(SIGNAL("UpdateCallback(int)"), pluginId)
  1641. elif action == CALLBACK_RELOAD_INFO:
  1642. Carla.gui.emit(SIGNAL("ReloadInfoCallback(int)"), pluginId)
  1643. elif action == CALLBACK_RELOAD_PARAMETERS:
  1644. Carla.gui.emit(SIGNAL("ReloadParametersCallback(int)"), pluginId)
  1645. elif action == CALLBACK_RELOAD_PROGRAMS:
  1646. Carla.gui.emit(SIGNAL("ReloadProgramsCallback(int)"), pluginId)
  1647. elif action == CALLBACK_RELOAD_ALL:
  1648. Carla.gui.emit(SIGNAL("ReloadAllCallback(int)"), pluginId)
  1649. elif action == CALLBACK_NSM_ANNOUNCE:
  1650. Carla.gui._nsmAnnounce2str = cString(Carla.Host.get_last_error())
  1651. Carla.gui.emit(SIGNAL("NSM_AnnounceCallback()"))
  1652. elif action == CALLBACK_NSM_OPEN1:
  1653. Carla.gui._nsmOpen1str = cString(Carla.Host.get_last_error())
  1654. Carla.gui.emit(SIGNAL("NSM_Open1Callback()"))
  1655. elif action == CALLBACK_NSM_OPEN2:
  1656. Carla.gui._nsmOpen2str = cString(Carla.Host.get_last_error())
  1657. Carla.gui.emit(SIGNAL("NSM_Open2Callback()"))
  1658. elif action == CALLBACK_NSM_SAVE:
  1659. Carla.gui.emit(SIGNAL("NSM_SaveCallback()"))
  1660. elif action == CALLBACK_QUIT:
  1661. Carla.gui.emit(SIGNAL("QuitCallback()"))
  1662. #--------------- main ------------------
  1663. if __name__ == '__main__':
  1664. # App initialization
  1665. app = QApplication(sys.argv)
  1666. app.setApplicationName("Carla")
  1667. app.setApplicationVersion(VERSION)
  1668. app.setOrganizationName("Cadence")
  1669. app.setWindowIcon(QIcon(":/scalable/carla.svg"))
  1670. libPrefix = None
  1671. projectFilename = None
  1672. for i in range(len(app.arguments())):
  1673. if i == 0: continue
  1674. argument = app.arguments()[i]
  1675. if argument.startswith("--with-libprefix="):
  1676. libPrefix = argument.replace("--with-libprefix=", "")
  1677. elif os.path.exists(argument):
  1678. projectFilename = argument
  1679. Carla.Host = Host(libPrefix)
  1680. Carla.Host.set_callback_function(callback_function)
  1681. Carla.Host.set_option(OPTION_PROCESS_NAME, 0, "carla")
  1682. # Set available drivers
  1683. driverCount = Carla.Host.get_engine_driver_count()
  1684. driverList = []
  1685. for i in range(driverCount):
  1686. driver = cString(Carla.Host.get_engine_driver_name(i))
  1687. if driver:
  1688. driverList.append(driver)
  1689. setAvailableEngineDrivers(driverList)
  1690. # Create GUI and start engine
  1691. Carla.gui = CarlaMainW()
  1692. # Set-up custom signal handling
  1693. setUpSignals(Carla.gui)
  1694. # Show GUI
  1695. Carla.gui.show()
  1696. if projectFilename:
  1697. Carla.gui.m_project_filename = projectFilename
  1698. Carla.gui.loadProjectLater()
  1699. Carla.gui.setWindowTitle("Carla - %s" % os.path.basename(projectFilename)) # FIXME - put in loadProject
  1700. # App-Loop
  1701. ret = app.exec_()
  1702. # Close Host
  1703. Carla.gui.stopEngine()
  1704. # Exit properly
  1705. sys.exit(ret)