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.

2231 lines
94KB

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