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.

3554 lines
144KB

  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. # Special rule for AVLinux
  18. AVLINUX_PY2BUILD = False
  19. if AVLINUX_PY2BUILD:
  20. from sip import setapi
  21. setapi("QString", 2)
  22. setapi("QVariant", 2)
  23. # Imports (Global)
  24. import json, os, sys
  25. from sip import unwrapinstance
  26. from PyQt4.QtCore import pyqtSlot, Qt, QSettings, QTimer, QThread
  27. from PyQt4.QtGui import QApplication, QColor, QCursor, QDialog, QFontMetrics, QInputDialog, QFrame, QMainWindow, QMenu, QPainter, QTableWidgetItem, QVBoxLayout, QWidget
  28. from PyQt4.QtXml import QDomDocument
  29. # Imports (Custom Stuff)
  30. import ui_carla, ui_carla_about, ui_carla_database, ui_carla_edit, ui_carla_parameter, ui_carla_plugin, ui_carla_refresh
  31. from carla_backend import *
  32. from shared_settings import *
  33. ICON_STATE_NULL = 0
  34. ICON_STATE_WAIT = 1
  35. ICON_STATE_OFF = 2
  36. ICON_STATE_ON = 3
  37. PALETTE_COLOR_NONE = 0
  38. PALETTE_COLOR_WHITE = 1
  39. PALETTE_COLOR_RED = 2
  40. PALETTE_COLOR_GREEN = 3
  41. PALETTE_COLOR_BLUE = 4
  42. PALETTE_COLOR_YELLOW = 5
  43. PALETTE_COLOR_ORANGE = 6
  44. PALETTE_COLOR_BROWN = 7
  45. PALETTE_COLOR_PINK = 8
  46. # Save support
  47. save_state_dict = {
  48. 'Type': "",
  49. 'Name': "",
  50. 'Label': "",
  51. 'Binary': "",
  52. 'UniqueID': 0,
  53. 'Active': False,
  54. 'DryWet': 1.0,
  55. 'Volume': 1.0,
  56. 'Balance-Left': -1.0,
  57. 'Balance-Right': 1.0,
  58. 'Parameters': [],
  59. 'CurrentProgramIndex': -1,
  60. 'CurrentProgramName': "",
  61. 'CurrentMidiBank': -1,
  62. 'CurrentMidiProgram': -1,
  63. 'CustomData': [],
  64. 'Chunk': None
  65. }
  66. save_state_parameter = {
  67. 'index': 0,
  68. 'name': "",
  69. 'symbol': "",
  70. 'value': 0.0,
  71. 'midi_channel': 1,
  72. 'midi_cc': -1
  73. }
  74. save_state_custom_data = {
  75. 'type': CUSTOM_DATA_INVALID,
  76. 'key': "",
  77. 'value': ""
  78. }
  79. # set defaults
  80. DEFAULT_PROJECT_FOLDER = HOME
  81. setDefaultProjectFolder(DEFAULT_PROJECT_FOLDER)
  82. setDefaultPluginsPaths(LADSPA_PATH, DSSI_PATH, LV2_PATH, VST_PATH, GIG_PATH, SF2_PATH, SFZ_PATH)
  83. def CustomDataType2String(dtype):
  84. if dtype == CUSTOM_DATA_STRING:
  85. return "string"
  86. elif dtype == CUSTOM_DATA_PATH:
  87. return "path"
  88. elif dtype == CUSTOM_DATA_CHUNK:
  89. return "chunk"
  90. elif dtype == CUSTOM_DATA_BINARY:
  91. return "binary"
  92. else:
  93. return "null"
  94. def CustomDataString2Type(stype):
  95. if stype == "string":
  96. return CUSTOM_DATA_STRING
  97. elif stype == "path":
  98. return CUSTOM_DATA_PATH
  99. elif stype == "chunk":
  100. return CUSTOM_DATA_CHUNK
  101. elif stype == "binary":
  102. return CUSTOM_DATA_BINARY
  103. else:
  104. return CUSTOM_DATA_INVALID
  105. def xmlSafeString(string, toXml):
  106. if toXml:
  107. return string.replace("&", "&amp;").replace("<","&lt;").replace(">","&gt;").replace("'","&apos;").replace("\"","&quot;")
  108. else:
  109. return string.replace("&amp;", "&").replace("&lt;","<").replace("&gt;",">").replace("&apos;","'").replace("&quot;","\"")
  110. def getStateDictFromXML(xml_node):
  111. x_save_state_dict = deepcopy(save_state_dict)
  112. node = xml_node.firstChild()
  113. while not node.isNull():
  114. if (node.toElement().tagName() == "Info"):
  115. xml_info = node.toElement().firstChild()
  116. while not xml_info.isNull():
  117. tag = xml_info.toElement().tagName()
  118. text = xml_info.toElement().text().strip()
  119. if tag == "Type":
  120. x_save_state_dict['Type'] = text
  121. elif tag == "Name":
  122. x_save_state_dict['Name'] = xmlSafeString(text, False)
  123. elif tag in ("Label", "URI"):
  124. x_save_state_dict['Label'] = xmlSafeString(text, False)
  125. elif tag == "Binary":
  126. x_save_state_dict['Binary'] = xmlSafeString(text, False)
  127. elif tag == "UniqueID":
  128. if text.isdigit():
  129. x_save_state_dict['UniqueID'] = int(text)
  130. xml_info = xml_info.nextSibling()
  131. elif (node.toElement().tagName() == "Data"):
  132. xml_data = node.toElement().firstChild()
  133. while not xml_data.isNull():
  134. tag = xml_data.toElement().tagName()
  135. text = xml_data.toElement().text().strip()
  136. if tag == "Active":
  137. x_save_state_dict['Active'] = bool(text == "Yes")
  138. elif tag == "DryWet":
  139. if isNumber(text):
  140. x_save_state_dict['DryWet'] = float(text)
  141. elif (tag == "Vol"):
  142. if isNumber(text):
  143. x_save_state_dict['Volume'] = float(text)
  144. elif (tag == "Balance-Left"):
  145. if isNumber(text):
  146. x_save_state_dict['Balance-Left'] = float(text)
  147. elif (tag == "Balance-Right"):
  148. if isNumber(text):
  149. x_save_state_dict['Balance-Right'] = float(text)
  150. elif tag == "CurrentProgramIndex":
  151. if text.isdigit():
  152. x_save_state_dict['CurrentProgramIndex'] = int(text)
  153. elif tag == "CurrentProgramName":
  154. x_save_state_dict['CurrentProgramName'] = xmlSafeString(text, False)
  155. elif tag == "CurrentMidiBank":
  156. if text.isdigit():
  157. x_save_state_dict['CurrentMidiBank'] = int(text)
  158. elif tag == "CurrentMidiProgram":
  159. if text.isdigit():
  160. x_save_state_dict['CurrentMidiProgram'] = int(text)
  161. elif tag == "Parameter":
  162. x_save_state_parameter = deepcopy(save_state_parameter)
  163. xml_subdata = xml_data.toElement().firstChild()
  164. while not xml_subdata.isNull():
  165. ptag = xml_subdata.toElement().tagName()
  166. ptext = xml_subdata.toElement().text().strip()
  167. if ptag == "index":
  168. if ptext.isdigit():
  169. x_save_state_parameter['index'] = int(ptext)
  170. elif ptag == "name":
  171. x_save_state_parameter['name'] = xmlSafeString(ptext, False)
  172. elif ptag == "symbol":
  173. x_save_state_parameter['symbol'] = xmlSafeString(ptext, False)
  174. elif ptag == "value":
  175. if isNumber(ptext):
  176. x_save_state_parameter['value'] = float(ptext)
  177. elif ptag == "midi_channel":
  178. if ptext.isdigit():
  179. x_save_state_parameter['midi_channel'] = int(ptext)
  180. elif ptag == "midi_cc":
  181. if ptext.isdigit():
  182. x_save_state_parameter['midi_cc'] = int(ptext)
  183. xml_subdata = xml_subdata.nextSibling()
  184. x_save_state_dict['Parameters'].append(x_save_state_parameter)
  185. elif (tag == "CustomData"):
  186. x_save_state_custom_data = deepcopy(save_state_custom_data)
  187. xml_subdata = xml_data.toElement().firstChild()
  188. while not xml_subdata.isNull():
  189. ctag = xml_subdata.toElement().tagName()
  190. ctext = xml_subdata.toElement().text().strip()
  191. if ctag == "type":
  192. x_save_state_custom_data['type'] = CustomDataString2Type(ctext)
  193. elif ctag == "key":
  194. x_save_state_custom_data['key'] = xmlSafeString(ctext, False)
  195. elif ctag == "value":
  196. x_save_state_custom_data['value'] = xmlSafeString(ctext, False)
  197. xml_subdata = xml_subdata.nextSibling()
  198. x_save_state_dict['CustomData'].append(x_save_state_custom_data)
  199. elif tag == "Chunk":
  200. x_save_state_dict['Chunk'] = text
  201. xml_data = xml_data.nextSibling()
  202. node = node.nextSibling()
  203. return x_save_state_dict
  204. # Separate Thread for Plugin Search
  205. class SearchPluginsThread(QThread):
  206. def __init__(self, parent):
  207. QThread.__init__(self, parent)
  208. self.settings_db = self.parent().settings_db
  209. self.tool_native = None
  210. self.check_unix32 = False
  211. self.check_unix64 = False
  212. self.check_win32 = False
  213. self.check_win64 = False
  214. self.check_ladspa = False
  215. self.check_dssi = False
  216. self.check_lv2 = False
  217. self.check_vst = False
  218. self.check_gig = False
  219. self.check_sf2 = False
  220. self.check_sfz = False
  221. def skipPlugin(self):
  222. # TODO - windows and mac support
  223. apps = ""
  224. apps += " carla-discovery"
  225. apps += " carla-discovery-unix32"
  226. apps += " carla-discovery-unix64"
  227. apps += " carla-discovery-win32.exe"
  228. apps += " carla-discovery-win64.exe"
  229. if LINUX:
  230. os.system("killall -KILL %s" % apps)
  231. def pluginLook(self, percent, plugin):
  232. self.emit(SIGNAL("PluginLook(int, QString)"), percent, plugin)
  233. def setSearchBinaryTypes(self, unix32, unix64, win32, win64):
  234. self.check_unix32 = unix32
  235. self.check_unix64 = unix64
  236. self.check_win32 = win32
  237. self.check_win64 = win64
  238. def setSearchPluginTypes(self, ladspa, dssi, lv2, vst, gig, sf2, sfz):
  239. self.check_ladspa = ladspa
  240. self.check_dssi = dssi
  241. self.check_lv2 = lv2
  242. self.check_vst = vst
  243. self.check_gig = gig
  244. self.check_sf2 = sf2
  245. self.check_sfz = sfz
  246. def setSearchToolNative(self, tool):
  247. self.tool_native = tool
  248. def setLastLoadedBinary(self, binary):
  249. self.settings_db.setValue("Plugins/LastLoadedBinary", binary)
  250. def checkLADSPA(self, OS, tool, isWine=False):
  251. global LADSPA_PATH
  252. ladspa_binaries = []
  253. self.ladspa_plugins = []
  254. for iPATH in LADSPA_PATH:
  255. binaries = findBinaries(iPATH, OS)
  256. for binary in binaries:
  257. if binary not in ladspa_binaries:
  258. ladspa_binaries.append(binary)
  259. ladspa_binaries.sort()
  260. for i in range(len(ladspa_binaries)):
  261. ladspa = ladspa_binaries[i]
  262. if os.path.basename(ladspa) in self.blacklist:
  263. print("plugin %s is blacklisted, skip it" % ladspa)
  264. continue
  265. else:
  266. percent = ( float(i) / len(ladspa_binaries) ) * self.m_percent_value
  267. self.pluginLook((self.m_last_value + percent) * 0.9, ladspa)
  268. self.setLastLoadedBinary(ladspa)
  269. plugins = checkPluginLADSPA(ladspa, tool, isWine)
  270. if plugins:
  271. self.ladspa_plugins.append(plugins)
  272. self.m_last_value += self.m_percent_value
  273. self.setLastLoadedBinary("")
  274. def checkDSSI(self, OS, tool, isWine=False):
  275. global DSSI_PATH
  276. dssi_binaries = []
  277. self.dssi_plugins = []
  278. for iPATH in DSSI_PATH:
  279. binaries = findBinaries(iPATH, OS)
  280. for binary in binaries:
  281. if binary not in dssi_binaries:
  282. dssi_binaries.append(binary)
  283. dssi_binaries.sort()
  284. for i in range(len(dssi_binaries)):
  285. dssi = dssi_binaries[i]
  286. if os.path.basename(dssi) in self.blacklist:
  287. print("plugin %s is blacklisted, skip it" % dssi)
  288. continue
  289. else:
  290. percent = ( float(i) / len(dssi_binaries) ) * self.m_percent_value
  291. self.pluginLook(self.m_last_value + percent, dssi)
  292. self.setLastLoadedBinary(dssi)
  293. plugins = checkPluginDSSI(dssi, tool, isWine)
  294. if plugins:
  295. self.dssi_plugins.append(plugins)
  296. self.m_last_value += self.m_percent_value
  297. self.setLastLoadedBinary("")
  298. def checkLV2(self, tool, isWine=False):
  299. global LV2_PATH
  300. lv2_bundles = []
  301. self.lv2_plugins = []
  302. self.pluginLook(self.m_last_value, "LV2 bundles...")
  303. for iPATH in LV2_PATH:
  304. bundles = findLV2Bundles(iPATH)
  305. for bundle in bundles:
  306. if bundle not in lv2_bundles:
  307. lv2_bundles.append(bundle)
  308. lv2_bundles.sort()
  309. for i in range(len(lv2_bundles)):
  310. lv2 = lv2_bundles[i]
  311. if (os.path.basename(lv2) in self.blacklist):
  312. print("bundle %s is blacklisted, skip it" % lv2)
  313. continue
  314. else:
  315. percent = ( float(i) / len(lv2_bundles) ) * self.m_percent_value
  316. self.pluginLook(self.m_last_value + percent, lv2)
  317. self.setLastLoadedBinary(lv2)
  318. plugins = checkPluginLV2(lv2, tool, isWine)
  319. if plugins:
  320. self.lv2_plugins.append(plugins)
  321. self.m_last_value += self.m_percent_value
  322. self.setLastLoadedBinary("")
  323. def checkVST(self, OS, tool, isWine=False):
  324. global VST_PATH
  325. vst_binaries = []
  326. self.vst_plugins = []
  327. for iPATH in VST_PATH:
  328. binaries = findBinaries(iPATH, OS)
  329. for binary in binaries:
  330. if binary not in vst_binaries:
  331. vst_binaries.append(binary)
  332. vst_binaries.sort()
  333. for i in range(len(vst_binaries)):
  334. vst = vst_binaries[i]
  335. if os.path.basename(vst) in self.blacklist:
  336. print("plugin %s is blacklisted, skip it" % vst)
  337. continue
  338. else:
  339. percent = ( float(i) / len(vst_binaries) ) * self.m_percent_value
  340. self.pluginLook(self.m_last_value + percent, vst)
  341. self.setLastLoadedBinary(vst)
  342. plugins = checkPluginVST(vst, tool, isWine)
  343. if plugins:
  344. self.vst_plugins.append(plugins)
  345. self.m_last_value += self.m_percent_value
  346. self.setLastLoadedBinary("")
  347. def checkKIT(self, kPATH, kType):
  348. kit_files = []
  349. self.kit_plugins = []
  350. for iPATH in kPATH:
  351. files = findSoundKits(iPATH, kType)
  352. for file_ in files:
  353. if file_ not in kit_files:
  354. kit_files.append(file_)
  355. kit_files.sort()
  356. for i in range(len(kit_files)):
  357. kit = kit_files[i]
  358. if os.path.basename(kit) in self.blacklist:
  359. print("plugin %s is blacklisted, skip it" % kit)
  360. continue
  361. else:
  362. percent = ( float(i) / len(kit_files) ) * self.m_percent_value
  363. self.pluginLook(self.m_last_value + percent, kit)
  364. self.setLastLoadedBinary(kit)
  365. if kType == "gig":
  366. plugins = checkPluginGIG(kit, self.tool_native)
  367. elif kType == "sf2":
  368. plugins = checkPluginSF2(kit, self.tool_native)
  369. elif kType == "sfz":
  370. plugins = checkPluginSFZ(kit, self.tool_native)
  371. else:
  372. plugins = None
  373. if plugins:
  374. self.kit_plugins.append(plugins)
  375. self.m_last_value += self.m_percent_value
  376. self.setLastLoadedBinary("")
  377. def run(self):
  378. global LADSPA_PATH, DSSI_PATH, LV2_PATH, VST_PATH, GIG_PATH, SF2_PATH, SFZ_PATH
  379. os.environ['LADSPA_PATH'] = splitter.join(LADSPA_PATH)
  380. os.environ['DSSI_PATH'] = splitter.join(DSSI_PATH)
  381. os.environ['LV2_PATH'] = splitter.join(LV2_PATH)
  382. os.environ['VST_PATH'] = splitter.join(VST_PATH)
  383. os.environ['GIG_PATH'] = splitter.join(GIG_PATH)
  384. os.environ['SF2_PATH'] = splitter.join(SF2_PATH)
  385. os.environ['SFZ_PATH'] = splitter.join(SFZ_PATH)
  386. self.blacklist = toList(self.settings_db.value("Plugins/Blacklisted", []))
  387. self.m_count = 0
  388. plugin_count = 0
  389. if self.check_ladspa: plugin_count += 1
  390. if self.check_dssi: plugin_count += 1
  391. if self.check_lv2: plugin_count += 1
  392. if self.check_vst: plugin_count += 1
  393. if self.check_unix32:
  394. self.m_count += plugin_count
  395. if self.check_unix64:
  396. self.m_count += plugin_count
  397. if self.check_win32:
  398. self.m_count += plugin_count
  399. if self.check_win64:
  400. self.m_count += plugin_count
  401. if self.tool_native:
  402. if self.check_gig: self.m_count += 1
  403. if self.check_sf2: self.m_count += 1
  404. if self.check_sfz: self.m_count += 1
  405. else:
  406. self.check_gig = False
  407. self.check_sf2 = False
  408. self.check_sfz = False
  409. if self.m_count == 0:
  410. return
  411. self.m_last_value = 0
  412. self.m_percent_value = 100 / self.m_count
  413. if LINUX:
  414. OS = "LINUX"
  415. elif MACOS:
  416. OS = "MACOS"
  417. elif WINDOWS:
  418. OS = "WINDOWS"
  419. else:
  420. OS = "UNKNOWN"
  421. if self.check_ladspa:
  422. m_value = 0
  423. if haveLRDF:
  424. if self.check_unix32: m_value += 0.1
  425. if self.check_unix64: m_value += 0.1
  426. if self.check_win32: m_value += 0.1
  427. if self.check_win64: m_value += 0.1
  428. rdf_pad_value = self.m_percent_value * m_value
  429. if self.check_unix32:
  430. self.checkLADSPA(OS, carla_discovery_unix32)
  431. self.settings_db.setValue("Plugins/LADSPA_unix32", self.ladspa_plugins)
  432. self.settings_db.sync()
  433. if self.check_unix64:
  434. self.checkLADSPA(OS, carla_discovery_unix64)
  435. self.settings_db.setValue("Plugins/LADSPA_unix64", self.ladspa_plugins)
  436. self.settings_db.sync()
  437. if self.check_win32:
  438. self.checkLADSPA("WINDOWS", carla_discovery_win32, not WINDOWS)
  439. self.settings_db.setValue("Plugins/LADSPA_win32", self.ladspa_plugins)
  440. self.settings_db.sync()
  441. if self.check_win64:
  442. self.checkLADSPA("WINDOWS", carla_discovery_win64, not WINDOWS)
  443. self.settings_db.setValue("Plugins/LADSPA_win64", self.ladspa_plugins)
  444. self.settings_db.sync()
  445. if haveLRDF:
  446. if m_value > 0:
  447. start_value = self.m_last_value - rdf_pad_value
  448. self.pluginLook(start_value, "LADSPA RDFs...")
  449. ladspa_rdf_info = ladspa_rdf.recheck_all_plugins(self, start_value, self.m_percent_value, m_value)
  450. SettingsDir = os.path.join(HOME, ".config", "Cadence")
  451. f_ladspa = open(os.path.join(SettingsDir, "ladspa_rdf.db"), 'w')
  452. if f_ladspa:
  453. json.dump(ladspa_rdf_info, f_ladspa)
  454. f_ladspa.close()
  455. if self.check_dssi:
  456. if self.check_unix32:
  457. self.checkDSSI(OS, carla_discovery_unix32)
  458. self.settings_db.setValue("Plugins/DSSI_unix32", self.dssi_plugins)
  459. self.settings_db.sync()
  460. if self.check_unix64:
  461. self.checkDSSI(OS, carla_discovery_unix64)
  462. self.settings_db.setValue("Plugins/DSSI_unix64", self.dssi_plugins)
  463. self.settings_db.sync()
  464. if self.check_win32:
  465. self.checkDSSI("WINDOWS", carla_discovery_win32, not WINDOWS)
  466. self.settings_db.setValue("Plugins/DSSI_win32", self.dssi_plugins)
  467. self.settings_db.sync()
  468. if self.check_win64:
  469. self.checkDSSI("WINDOWS", carla_discovery_win64, not WINDOWS)
  470. self.settings_db.setValue("Plugins/DSSI_win64", self.dssi_plugins)
  471. self.settings_db.sync()
  472. if self.check_lv2:
  473. if self.check_unix32:
  474. self.checkLV2(carla_discovery_unix32)
  475. self.settings_db.setValue("Plugins/LV2_unix32", self.lv2_plugins)
  476. self.settings_db.sync()
  477. if self.check_unix64:
  478. self.checkLV2(carla_discovery_unix64)
  479. self.settings_db.setValue("Plugins/LV2_unix64", self.lv2_plugins)
  480. self.settings_db.sync()
  481. if self.check_win32:
  482. self.checkLV2(carla_discovery_win32, not WINDOWS)
  483. self.settings_db.setValue("Plugins/LV2_win32", self.lv2_plugins)
  484. self.settings_db.sync()
  485. if self.check_win64:
  486. self.checkLV2(carla_discovery_win64, not WINDOWS)
  487. self.settings_db.setValue("Plugins/LV2_win64", self.lv2_plugins)
  488. self.settings_db.sync()
  489. if self.check_vst:
  490. if self.check_unix32:
  491. self.checkVST(OS, carla_discovery_unix32)
  492. self.settings_db.setValue("Plugins/VST_unix32", self.vst_plugins)
  493. self.settings_db.sync()
  494. if self.check_unix64:
  495. self.checkVST(OS, carla_discovery_unix64)
  496. self.settings_db.setValue("Plugins/VST_unix64", self.vst_plugins)
  497. self.settings_db.sync()
  498. if self.check_win32:
  499. self.checkVST("WINDOWS", carla_discovery_win32, not WINDOWS)
  500. self.settings_db.setValue("Plugins/VST_win32", self.vst_plugins)
  501. self.settings_db.sync()
  502. if self.check_win64:
  503. self.checkVST("WINDOWS", carla_discovery_win64, not WINDOWS)
  504. self.settings_db.setValue("Plugins/VST_win64", self.vst_plugins)
  505. self.settings_db.sync()
  506. if self.check_gig:
  507. self.checkKIT(GIG_PATH, "gig")
  508. self.settings_db.setValue("Plugins/GIG", self.kit_plugins)
  509. self.settings_db.sync()
  510. if self.check_sf2:
  511. self.checkKIT(SF2_PATH, "sf2")
  512. self.settings_db.setValue("Plugins/SF2", self.kit_plugins)
  513. self.settings_db.sync()
  514. if self.check_sfz:
  515. self.checkKIT(SFZ_PATH, "sfz")
  516. self.settings_db.setValue("Plugins/SFZ", self.kit_plugins)
  517. self.settings_db.sync()
  518. # Plugin Refresh Dialog
  519. class PluginRefreshW(QDialog, ui_carla_refresh.Ui_PluginRefreshW):
  520. def __init__(self, parent):
  521. QDialog.__init__(self, parent)
  522. self.setupUi(self)
  523. self.b_skip.setVisible(False)
  524. if LINUX:
  525. self.ch_unix32.setText("Linux 32bit")
  526. self.ch_unix64.setText("Linux 64bit")
  527. elif MACOS:
  528. self.ch_unix32.setText("MacOS 32bit")
  529. self.ch_unix64.setText("MacOS 64bit")
  530. self.settings = self.parent().settings
  531. self.settings_db = self.parent().settings_db
  532. self.loadSettings()
  533. self.pThread = SearchPluginsThread(self)
  534. if carla_discovery_unix32 and not WINDOWS:
  535. self.ico_unix32.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  536. else:
  537. self.ico_unix32.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  538. self.ch_unix32.setChecked(False)
  539. self.ch_unix32.setEnabled(False)
  540. if carla_discovery_unix64 and not WINDOWS:
  541. self.ico_unix64.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  542. else:
  543. self.ico_unix64.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  544. self.ch_unix64.setChecked(False)
  545. self.ch_unix64.setEnabled(False)
  546. if carla_discovery_win32:
  547. self.ico_win32.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  548. else:
  549. self.ico_win32.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  550. self.ch_win32.setChecked(False)
  551. self.ch_win32.setEnabled(False)
  552. if carla_discovery_win64:
  553. self.ico_win64.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  554. else:
  555. self.ico_win64.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  556. self.ch_win64.setChecked(False)
  557. self.ch_win64.setEnabled(False)
  558. if haveLRDF:
  559. self.ico_rdflib.setPixmap(getIcon("dialog-ok-apply").pixmap(16, 16))
  560. else:
  561. self.ico_rdflib.setPixmap(getIcon("dialog-error").pixmap(16, 16))
  562. hasNative = False
  563. hasNonNative = False
  564. if LINUX or MACOS:
  565. if is64bit:
  566. hasNative = bool(carla_discovery_unix64)
  567. hasNonNative = bool(carla_discovery_unix32 or carla_discovery_win32 or carla_discovery_win64)
  568. self.pThread.setSearchToolNative(carla_discovery_unix64)
  569. else:
  570. hasNative = bool(carla_discovery_unix32)
  571. hasNonNative = bool(carla_discovery_unix64 or carla_discovery_win32 or carla_discovery_win64)
  572. self.pThread.setSearchToolNative(carla_discovery_unix32)
  573. elif WINDOWS:
  574. if is64bit:
  575. hasNative = bool(carla_discovery_win64)
  576. hasNonNative = bool(carla_discovery_win32)
  577. self.pThread.setSearchToolNative(carla_discovery_win64)
  578. else:
  579. hasNative = bool(carla_discovery_win32)
  580. hasNonNative = bool(carla_discovery_win64)
  581. self.pThread.setSearchToolNative(carla_discovery_win32)
  582. if not hasNative:
  583. self.ch_gig.setChecked(False)
  584. self.ch_gig.setEnabled(False)
  585. self.ch_sf2.setChecked(False)
  586. self.ch_sf2.setEnabled(False)
  587. self.ch_sfz.setChecked(False)
  588. self.ch_sfz.setEnabled(False)
  589. if not hasNonNative:
  590. self.ch_ladspa.setChecked(False)
  591. self.ch_ladspa.setEnabled(False)
  592. self.ch_dssi.setChecked(False)
  593. self.ch_dssi.setEnabled(False)
  594. self.ch_vst.setChecked(False)
  595. self.ch_vst.setEnabled(False)
  596. self.b_refresh.setEnabled(False)
  597. self.connect(self.b_refresh, SIGNAL("clicked()"), SLOT("slot_refresh_plugins()"))
  598. self.connect(self.b_skip, SIGNAL("clicked()"), SLOT("slot_skip()"))
  599. self.connect(self.pThread, SIGNAL("PluginLook(int, QString)"), SLOT("slot_handlePluginLook(int, QString)"))
  600. self.connect(self.pThread, SIGNAL("finished()"), SLOT("slot_handlePluginThreadFinished()"))
  601. @pyqtSlot()
  602. def slot_refresh_plugins(self):
  603. self.progressBar.setMinimum(0)
  604. self.progressBar.setMaximum(100)
  605. self.progressBar.setValue(0)
  606. self.b_refresh.setEnabled(False)
  607. self.b_skip.setVisible(True)
  608. self.b_close.setVisible(False)
  609. unix32, unix64, win32, win64 = (self.ch_unix32.isChecked(), self.ch_unix64.isChecked(), self.ch_win32.isChecked(), self.ch_win64.isChecked())
  610. ladspa, dssi, lv2, vst, gig, sf2, sfz = (self.ch_ladspa.isChecked(), self.ch_dssi.isChecked(), self.ch_lv2.isChecked(), self.ch_vst.isChecked(),
  611. self.ch_gig.isChecked(), self.ch_sf2.isChecked(), self.ch_sfz.isChecked())
  612. self.pThread.setSearchBinaryTypes(unix32, unix64, win32, win64)
  613. self.pThread.setSearchPluginTypes(ladspa, dssi, lv2, vst, gig, sf2, sfz)
  614. self.pThread.start()
  615. @pyqtSlot()
  616. def slot_skip(self):
  617. self.pThread.skipPlugin()
  618. @pyqtSlot(int, str)
  619. def slot_handlePluginLook(self, percent, plugin):
  620. self.progressBar.setFormat("%s" % (plugin))
  621. self.progressBar.setValue(percent)
  622. @pyqtSlot()
  623. def slot_handlePluginThreadFinished(self):
  624. self.progressBar.setMinimum(0)
  625. self.progressBar.setMaximum(1)
  626. self.progressBar.setValue(1)
  627. self.progressBar.setFormat(self.tr("Done"))
  628. self.b_refresh.setEnabled(True)
  629. self.b_skip.setVisible(False)
  630. self.b_close.setVisible(True)
  631. def saveSettings(self):
  632. self.settings.setValue("PluginDatabase/SearchLADSPA", self.ch_ladspa.isChecked())
  633. self.settings.setValue("PluginDatabase/SearchDSSI", self.ch_dssi.isChecked())
  634. self.settings.setValue("PluginDatabase/SearchLV2", self.ch_lv2.isChecked())
  635. self.settings.setValue("PluginDatabase/SearchVST", self.ch_vst.isChecked())
  636. self.settings.setValue("PluginDatabase/SearchGIG", self.ch_gig.isChecked())
  637. self.settings.setValue("PluginDatabase/SearchSF2", self.ch_sf2.isChecked())
  638. self.settings.setValue("PluginDatabase/SearchSFZ", self.ch_sfz.isChecked())
  639. self.settings.setValue("PluginDatabase/SearchUnix32", self.ch_unix32.isChecked())
  640. self.settings.setValue("PluginDatabase/SearchUnix64", self.ch_unix64.isChecked())
  641. self.settings.setValue("PluginDatabase/SearchWin32", self.ch_win32.isChecked())
  642. self.settings.setValue("PluginDatabase/SearchWin64", self.ch_win64.isChecked())
  643. self.settings_db.setValue("Plugins/LastLoadedBinary", "")
  644. def loadSettings(self):
  645. self.ch_ladspa.setChecked(self.settings.value("PluginDatabase/SearchLADSPA", True, type=bool))
  646. self.ch_dssi.setChecked(self.settings.value("PluginDatabase/SearchDSSI", True, type=bool))
  647. self.ch_lv2.setChecked(self.settings.value("PluginDatabase/SearchLV2", True, type=bool))
  648. self.ch_vst.setChecked(self.settings.value("PluginDatabase/SearchVST", True, type=bool))
  649. self.ch_gig.setChecked(self.settings.value("PluginDatabase/SearchGIG", True, type=bool))
  650. self.ch_sf2.setChecked(self.settings.value("PluginDatabase/SearchSF2", True, type=bool))
  651. self.ch_sfz.setChecked(self.settings.value("PluginDatabase/SearchSFZ", True, type=bool))
  652. self.ch_unix32.setChecked(self.settings.value("PluginDatabase/SearchUnix32", True, type=bool))
  653. self.ch_unix64.setChecked(self.settings.value("PluginDatabase/SearchUnix64", True, type=bool))
  654. self.ch_win32.setChecked(self.settings.value("PluginDatabase/SearchWin32", True, type=bool))
  655. self.ch_win64.setChecked(self.settings.value("PluginDatabase/SearchWin64", True, type=bool))
  656. def closeEvent(self, event):
  657. if self.pThread.isRunning():
  658. self.pThread.terminate()
  659. self.pThread.wait()
  660. self.saveSettings()
  661. QDialog.closeEvent(self, event)
  662. def done(self, r):
  663. QDialog.done(self, r)
  664. self.close()
  665. # Plugin Database Dialog
  666. class PluginDatabaseW(QDialog, ui_carla_database.Ui_PluginDatabaseW):
  667. def __init__(self, parent):
  668. QDialog.__init__(self, parent)
  669. self.setupUi(self)
  670. self.warning_old_shown = False
  671. self.b_add.setEnabled(False)
  672. if BINARY_NATIVE in (BINARY_UNIX32, BINARY_WIN32):
  673. self.ch_bridged.setText(self.tr("Bridged (64bit)"))
  674. else:
  675. self.ch_bridged.setText(self.tr("Bridged (32bit)"))
  676. self.settings = self.parent().settings
  677. self.settings_db = self.parent().settings_db
  678. self.loadSettings()
  679. if not (LINUX or MACOS):
  680. self.ch_bridged_wine.setChecked(False)
  681. self.ch_bridged_wine.setEnabled(False)
  682. # Blacklist plugins
  683. if not self.settings_db.contains("Plugins/Blacklisted"):
  684. blacklist = [] # FIXME
  685. # Broken or useless plugins
  686. #blacklist.append("dssi-vst.so")
  687. blacklist.append("liteon_biquad-vst.so")
  688. blacklist.append("liteon_biquad-vst_64bit.so")
  689. blacklist.append("fx_blur-vst.so")
  690. blacklist.append("fx_blur-vst_64bit.so")
  691. blacklist.append("fx_tempodelay-vst.so")
  692. blacklist.append("Scrubby_64bit.so")
  693. blacklist.append("Skidder_64bit.so")
  694. blacklist.append("libwormhole2_64bit.so")
  695. blacklist.append("vexvst.so")
  696. #blacklist.append("deckadance.dll")
  697. self.settings_db.setValue("Plugins/Blacklisted", blacklist)
  698. self.connect(self.b_add, SIGNAL("clicked()"), SLOT("slot_add_plugin()"))
  699. self.connect(self.b_refresh, SIGNAL("clicked()"), SLOT("slot_refresh_plugins()"))
  700. self.connect(self.tb_filters, SIGNAL("clicked()"), SLOT("slot_maybe_show_filters()"))
  701. self.connect(self.tableWidget, SIGNAL("currentCellChanged(int, int, int, int)"), SLOT("slot_checkPlugin(int)"))
  702. self.connect(self.tableWidget, SIGNAL("cellDoubleClicked(int, int)"), SLOT("slot_add_plugin()"))
  703. self.connect(self.lineEdit, SIGNAL("textChanged(QString)"), SLOT("slot_checkFilters()"))
  704. self.connect(self.ch_effects, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  705. self.connect(self.ch_instruments, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  706. self.connect(self.ch_midi, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  707. self.connect(self.ch_other, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  708. self.connect(self.ch_kits, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  709. self.connect(self.ch_ladspa, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  710. self.connect(self.ch_dssi, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  711. self.connect(self.ch_lv2, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  712. self.connect(self.ch_vst, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  713. self.connect(self.ch_native, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  714. self.connect(self.ch_bridged, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  715. self.connect(self.ch_bridged_wine, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  716. self.connect(self.ch_gui, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  717. self.connect(self.ch_stereo, SIGNAL("clicked()"), SLOT("slot_checkFilters()"))
  718. self.ret_plugin = None
  719. def showFilters(self, yesno):
  720. self.tb_filters.setArrowType(Qt.UpArrow if yesno else Qt.DownArrow)
  721. self.frame.setVisible(yesno)
  722. def reAddPlugins(self):
  723. row_count = self.tableWidget.rowCount()
  724. for x in range(row_count):
  725. self.tableWidget.removeRow(0)
  726. self.last_table_index = 0
  727. self.tableWidget.setSortingEnabled(False)
  728. ladspa_plugins = []
  729. ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_unix32", []))
  730. ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_unix64", []))
  731. ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_win32", []))
  732. ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_win64", []))
  733. dssi_plugins = []
  734. dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_unix32", []))
  735. dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_unix64", []))
  736. dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_win32", []))
  737. dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_win64", []))
  738. lv2_plugins = []
  739. lv2_plugins += toList(self.settings_db.value("Plugins/LV2_unix32", []))
  740. lv2_plugins += toList(self.settings_db.value("Plugins/LV2_unix64", []))
  741. lv2_plugins += toList(self.settings_db.value("Plugins/LV2_win32", []))
  742. lv2_plugins += toList(self.settings_db.value("Plugins/LV2_win64", []))
  743. vst_plugins = []
  744. vst_plugins += toList(self.settings_db.value("Plugins/VST_unix32", []))
  745. vst_plugins += toList(self.settings_db.value("Plugins/VST_unix64", []))
  746. vst_plugins += toList(self.settings_db.value("Plugins/VST_win32", []))
  747. vst_plugins += toList(self.settings_db.value("Plugins/VST_win64", []))
  748. gigs = toList(self.settings_db.value("Plugins/GIG", []))
  749. sf2s = toList(self.settings_db.value("Plugins/SF2", []))
  750. sfzs = toList(self.settings_db.value("Plugins/SFZ", []))
  751. ladspa_count = 0
  752. dssi_count = 0
  753. lv2_count = 0
  754. vst_count = 0
  755. kit_count = 0
  756. for plugins in ladspa_plugins:
  757. for plugin in plugins:
  758. self.addPluginToTable(plugin, "LADSPA")
  759. ladspa_count += 1
  760. for plugins in dssi_plugins:
  761. for plugin in plugins:
  762. self.addPluginToTable(plugin, "DSSI")
  763. dssi_count += 1
  764. for plugins in lv2_plugins:
  765. for plugin in plugins:
  766. self.addPluginToTable(plugin, "LV2")
  767. lv2_count += 1
  768. for plugins in vst_plugins:
  769. for plugin in plugins:
  770. self.addPluginToTable(plugin, "VST")
  771. vst_count += 1
  772. for gig in gigs:
  773. for gig_i in gig:
  774. self.addPluginToTable(gig_i, "GIG")
  775. kit_count += 1
  776. for sf2 in sf2s:
  777. for sf2_i in sf2:
  778. self.addPluginToTable(sf2_i, "SF2")
  779. kit_count += 1
  780. for sfz in sfzs:
  781. for sfz_i in sfz:
  782. self.addPluginToTable(sfz_i, "SFZ")
  783. kit_count += 1
  784. self.slot_checkFilters()
  785. self.tableWidget.setSortingEnabled(True)
  786. self.tableWidget.sortByColumn(0, Qt.AscendingOrder)
  787. 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)))
  788. def addPluginToTable(self, plugin, ptype):
  789. index = self.last_table_index
  790. if "build" not in plugin.keys():
  791. if not self.warning_old_shown:
  792. QMessageBox.warning(self, self.tr("Warning"), self.tr("You're using a Carla-Database from an old version of Carla, please update the plugins"))
  793. self.warning_old_shown = True
  794. return
  795. if plugin['build'] == BINARY_NATIVE:
  796. bridge_text = self.tr("No")
  797. else:
  798. type_text = self.tr("Unknown")
  799. if LINUX or MACOS:
  800. if plugin['build'] == BINARY_UNIX32:
  801. type_text = "32bit"
  802. elif plugin['build'] == BINARY_UNIX64:
  803. type_text = "64bit"
  804. elif plugin['build'] == BINARY_WIN32:
  805. type_text = "Windows 32bit"
  806. elif plugin['build'] == BINARY_WIN64:
  807. type_text = "Windows 64bit"
  808. elif WINDOWS:
  809. if plugin['build'] == BINARY_WIN32:
  810. type_text = "32bit"
  811. elif plugin['build'] == BINARY_WIN64:
  812. type_text = "64bit"
  813. bridge_text = self.tr("Yes (%s)" % type_text)
  814. self.tableWidget.insertRow(index)
  815. self.tableWidget.setItem(index, 0, QTableWidgetItem(plugin['name']))
  816. self.tableWidget.setItem(index, 1, QTableWidgetItem(plugin['label']))
  817. self.tableWidget.setItem(index, 2, QTableWidgetItem(plugin['maker']))
  818. self.tableWidget.setItem(index, 3, QTableWidgetItem(str(plugin['unique_id'])))
  819. self.tableWidget.setItem(index, 4, QTableWidgetItem(str(plugin['audio.ins'])))
  820. self.tableWidget.setItem(index, 5, QTableWidgetItem(str(plugin['audio.outs'])))
  821. self.tableWidget.setItem(index, 6, QTableWidgetItem(str(plugin['parameters.ins'])))
  822. self.tableWidget.setItem(index, 7, QTableWidgetItem(str(plugin['parameters.outs'])))
  823. self.tableWidget.setItem(index, 8, QTableWidgetItem(str(plugin['programs.total'])))
  824. self.tableWidget.setItem(index, 9, QTableWidgetItem(self.tr("Yes") if (plugin['hints'] & PLUGIN_HAS_GUI) else self.tr("No")))
  825. self.tableWidget.setItem(index, 10, QTableWidgetItem(self.tr("Yes") if (plugin['hints'] & PLUGIN_IS_SYNTH) else self.tr("No")))
  826. self.tableWidget.setItem(index, 11, QTableWidgetItem(bridge_text))
  827. self.tableWidget.setItem(index, 12, QTableWidgetItem(ptype))
  828. self.tableWidget.setItem(index, 13, QTableWidgetItem(plugin['binary']))
  829. self.tableWidget.item(self.last_table_index, 0).plugin_data = plugin
  830. self.last_table_index += 1
  831. @pyqtSlot()
  832. def slot_add_plugin(self):
  833. if self.tableWidget.currentRow() >= 0:
  834. self.ret_plugin = self.tableWidget.item(self.tableWidget.currentRow(), 0).plugin_data
  835. self.accept()
  836. else:
  837. self.reject()
  838. @pyqtSlot()
  839. def slot_refresh_plugins(self):
  840. lastLoadedPlugin = self.settings_db.value("Plugins/LastLoadedBinary", "", type=str)
  841. if lastLoadedPlugin:
  842. lastLoadedPlugin = os.path.basename(lastLoadedPlugin)
  843. ask = QMessageBox.question(self, self.tr("Warning"), self.tr("There was an error while checking the plugin %s.\n"
  844. "Do you want to blacklist it?" % (lastLoadedPlugin)),
  845. QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
  846. if ask == QMessageBox.Yes:
  847. blacklist = toList(self.settings_db.value("Plugins/Blacklisted", []))
  848. blacklist.append(lastLoadedPlugin)
  849. self.settings_db.setValue("Plugins/Blacklisted", blacklist)
  850. #self.label.setText(self.tr("Looking for plugins..."))
  851. PluginRefreshW(self).exec_()
  852. self.reAddPlugins()
  853. self.parent().loadRDFs()
  854. @pyqtSlot()
  855. def slot_maybe_show_filters(self):
  856. self.showFilters(not self.frame.isVisible())
  857. @pyqtSlot(int)
  858. def slot_checkPlugin(self, row):
  859. self.b_add.setEnabled(row >= 0)
  860. @pyqtSlot()
  861. def slot_checkFilters(self):
  862. text = self.lineEdit.text().lower()
  863. hide_effects = not self.ch_effects.isChecked()
  864. hide_instruments = not self.ch_instruments.isChecked()
  865. hide_midi = not self.ch_midi.isChecked()
  866. hide_other = not self.ch_other.isChecked()
  867. hide_ladspa = not self.ch_ladspa.isChecked()
  868. hide_dssi = not self.ch_dssi.isChecked()
  869. hide_lv2 = not self.ch_lv2.isChecked()
  870. hide_vst = not self.ch_vst.isChecked()
  871. hide_kits = not self.ch_kits.isChecked()
  872. hide_native = not self.ch_native.isChecked()
  873. hide_bridged = not self.ch_bridged.isChecked()
  874. hide_bridged_wine = not self.ch_bridged_wine.isChecked()
  875. hide_non_gui = self.ch_gui.isChecked()
  876. hide_non_stereo = self.ch_stereo.isChecked()
  877. if LINUX or MACOS:
  878. native_bins = [BINARY_UNIX32, BINARY_UNIX64]
  879. wine_bins = [BINARY_WIN32, BINARY_WIN64]
  880. elif WINDOWS:
  881. native_bins = [BINARY_WIN32, BINARY_WIN64]
  882. wine_bins = []
  883. else:
  884. native_bins = []
  885. wine_bins = []
  886. row_count = self.tableWidget.rowCount()
  887. for i in range(row_count):
  888. self.tableWidget.showRow(i)
  889. plugin = self.tableWidget.item(i, 0).plugin_data
  890. ains = plugin['audio.ins']
  891. aouts = plugin['audio.outs']
  892. mins = plugin['midi.ins']
  893. mouts = plugin['midi.outs']
  894. ptype = self.tableWidget.item(i, 12).text()
  895. is_synth = bool(plugin['hints'] & PLUGIN_IS_SYNTH)
  896. is_effect = bool(ains > 0 < aouts and not is_synth)
  897. is_midi = bool(ains == 0 and aouts == 0 and mins > 0 < mouts)
  898. is_kit = bool(ptype in ("GIG", "SF2", "SFZ"))
  899. is_other = bool(not (is_effect or is_synth or is_midi or is_kit))
  900. is_native = bool(plugin['build'] == BINARY_NATIVE)
  901. is_stereo = bool(ains == 2 and aouts == 2) or (is_synth and aouts == 2)
  902. has_gui = bool(plugin['hints'] & PLUGIN_HAS_GUI)
  903. is_bridged = bool(not is_native and plugin['build'] in native_bins)
  904. is_bridged_wine = bool(not is_native and plugin['build'] in wine_bins)
  905. if (hide_effects and is_effect):
  906. self.tableWidget.hideRow(i)
  907. elif (hide_instruments and is_synth):
  908. self.tableWidget.hideRow(i)
  909. elif (hide_midi and is_midi):
  910. self.tableWidget.hideRow(i)
  911. elif (hide_other and is_other):
  912. self.tableWidget.hideRow(i)
  913. elif (hide_kits and is_kit):
  914. self.tableWidget.hideRow(i)
  915. elif (hide_ladspa and ptype == "LADSPA"):
  916. self.tableWidget.hideRow(i)
  917. elif (hide_dssi and ptype == "DSSI"):
  918. self.tableWidget.hideRow(i)
  919. elif (hide_lv2 and ptype == "LV2"):
  920. self.tableWidget.hideRow(i)
  921. elif (hide_vst and ptype == "VST"):
  922. self.tableWidget.hideRow(i)
  923. elif (hide_native and is_native):
  924. self.tableWidget.hideRow(i)
  925. elif (hide_bridged and is_bridged):
  926. self.tableWidget.hideRow(i)
  927. elif (hide_bridged_wine and is_bridged_wine):
  928. self.tableWidget.hideRow(i)
  929. elif (hide_non_gui and not has_gui):
  930. self.tableWidget.hideRow(i)
  931. elif (hide_non_stereo and not is_stereo):
  932. self.tableWidget.hideRow(i)
  933. elif (text and not (
  934. text in self.tableWidget.item(i, 0).text().lower() or
  935. text in self.tableWidget.item(i, 1).text().lower() or
  936. text in self.tableWidget.item(i, 2).text().lower() or
  937. text in self.tableWidget.item(i, 3).text().lower() or
  938. text in self.tableWidget.item(i, 13).text().lower())):
  939. self.tableWidget.hideRow(i)
  940. def saveSettings(self):
  941. self.settings.setValue("PluginDatabase/Geometry", self.saveGeometry())
  942. self.settings.setValue("PluginDatabase/TableGeometry", self.tableWidget.horizontalHeader().saveState())
  943. self.settings.setValue("PluginDatabase/ShowFilters", (self.tb_filters.arrowType() == Qt.UpArrow))
  944. self.settings.setValue("PluginDatabase/ShowEffects", self.ch_effects.isChecked())
  945. self.settings.setValue("PluginDatabase/ShowInstruments", self.ch_instruments.isChecked())
  946. self.settings.setValue("PluginDatabase/ShowMIDI", self.ch_midi.isChecked())
  947. self.settings.setValue("PluginDatabase/ShowOther", self.ch_other.isChecked())
  948. self.settings.setValue("PluginDatabase/ShowLADSPA", self.ch_ladspa.isChecked())
  949. self.settings.setValue("PluginDatabase/ShowDSSI", self.ch_dssi.isChecked())
  950. self.settings.setValue("PluginDatabase/ShowLV2", self.ch_lv2.isChecked())
  951. self.settings.setValue("PluginDatabase/ShowVST", self.ch_vst.isChecked())
  952. self.settings.setValue("PluginDatabase/ShowKits", self.ch_kits.isChecked())
  953. self.settings.setValue("PluginDatabase/ShowNative", self.ch_native.isChecked())
  954. self.settings.setValue("PluginDatabase/ShowBridged", self.ch_bridged.isChecked())
  955. self.settings.setValue("PluginDatabase/ShowBridgedWine", self.ch_bridged_wine.isChecked())
  956. self.settings.setValue("PluginDatabase/ShowHasGUI", self.ch_gui.isChecked())
  957. self.settings.setValue("PluginDatabase/ShowStereoOnly", self.ch_stereo.isChecked())
  958. def loadSettings(self):
  959. self.restoreGeometry(self.settings.value("PluginDatabase/Geometry", ""))
  960. self.tableWidget.horizontalHeader().restoreState(self.settings.value("PluginDatabase/TableGeometry", ""))
  961. self.showFilters(self.settings.value("PluginDatabase/ShowFilters", False, type=bool))
  962. self.ch_effects.setChecked(self.settings.value("PluginDatabase/ShowEffects", True, type=bool))
  963. self.ch_instruments.setChecked(self.settings.value("PluginDatabase/ShowInstruments", True, type=bool))
  964. self.ch_midi.setChecked(self.settings.value("PluginDatabase/ShowMIDI", True, type=bool))
  965. self.ch_other.setChecked(self.settings.value("PluginDatabase/ShowOther", True, type=bool))
  966. self.ch_ladspa.setChecked(self.settings.value("PluginDatabase/ShowLADSPA", True, type=bool))
  967. self.ch_dssi.setChecked(self.settings.value("PluginDatabase/ShowDSSI", True, type=bool))
  968. self.ch_lv2.setChecked(self.settings.value("PluginDatabase/ShowLV2", True, type=bool))
  969. self.ch_vst.setChecked(self.settings.value("PluginDatabase/ShowVST", True, type=bool))
  970. self.ch_kits.setChecked(self.settings.value("PluginDatabase/ShowKits", True, type=bool))
  971. self.ch_native.setChecked(self.settings.value("PluginDatabase/ShowNative", True, type=bool))
  972. self.ch_bridged.setChecked(self.settings.value("PluginDatabase/ShowBridged", True, type=bool))
  973. self.ch_bridged_wine.setChecked(self.settings.value("PluginDatabase/ShowBridgedWine", True, type=bool))
  974. self.ch_gui.setChecked(self.settings.value("PluginDatabase/ShowHasGUI", False, type=bool))
  975. self.ch_stereo.setChecked(self.settings.value("PluginDatabase/ShowStereoOnly", False, type=bool))
  976. self.reAddPlugins()
  977. def closeEvent(self, event):
  978. self.saveSettings()
  979. QDialog.closeEvent(self, event)
  980. def done(self, r):
  981. QDialog.done(self, r)
  982. self.close()
  983. # About Carla Dialog
  984. class CarlaAboutW(QDialog, ui_carla_about.Ui_CarlaAboutW):
  985. def __init__(self, parent=None):
  986. super(CarlaAboutW, self).__init__(parent)
  987. self.setupUi(self)
  988. self.l_about.setText(self.tr(""
  989. "<br>Version %s"
  990. "<br>Carla is a Multi-Plugin Host for JACK.<br>"
  991. "<br>Copyright (C) 2011-2012 falkTX<br>"
  992. "<br><i>VST is a trademark of Steinberg Media Technologies GmbH.</i>"
  993. "" % VERSION))
  994. host_osc_url = cString(CarlaHost.get_host_osc_url())
  995. self.le_osc_url.setText(host_osc_url)
  996. self.l_osc_cmds.setText(""
  997. " /set_active <i-value>\n"
  998. " /set_drywet <f-value>\n"
  999. " /set_vol <f-value>\n"
  1000. " /set_balance_left <f-value>\n"
  1001. " /set_balance_right <f-value>\n"
  1002. " /set_parameter <i-index> <f-value>\n"
  1003. " /set_program <i-index>\n"
  1004. " /set_midi_program <i-index>\n"
  1005. " /note_on <i-note> <i-velo>\n"
  1006. " /note_off <i-note> <i-velo>\n"
  1007. )
  1008. self.l_example.setText("/Carla/2/set_parameter_value 2 0.5")
  1009. self.l_example_help.setText("<i>(as in this example, \"2\" is the plugin number)</i>")
  1010. self.l_ladspa.setText(self.tr("Everything! (Including LRDF)"))
  1011. self.l_dssi.setText(self.tr("Everything! (Including CustomData/Chunks)"))
  1012. self.l_lv2.setText(self.tr("About 95&#37; complete (only missing minor features).<br/>"
  1013. "Implemented Feature/Extensions:"
  1014. "<ul>"
  1015. "<li>http://lv2plug.in/ns/ext/atom</li>"
  1016. "<li>http://lv2plug.in/ns/ext/data-access</li>"
  1017. "<li>http://lv2plug.in/ns/ext/event</li>"
  1018. "<li>http://lv2plug.in/ns/ext/instance-access</li>"
  1019. "<li>http://lv2plug.in/ns/ext/log</li>"
  1020. "<li>http://lv2plug.in/ns/ext/midi</li>"
  1021. #"<li>http://lv2plug.in/ns/ext/patch</li>"
  1022. "<li>http://lv2plug.in/ns/ext/port-props</li>"
  1023. #"<li>http://lv2plug.in/ns/ext/presets</li>"
  1024. "<li>http://lv2plug.in/ns/ext/state</li>"
  1025. #"<li>http://lv2plug.in/ns/ext/time</li>"
  1026. "<li>http://lv2plug.in/ns/ext/uri-map</li>"
  1027. "<li>http://lv2plug.in/ns/ext/urid</li>"
  1028. "<li>http://lv2plug.in/ns/ext/worker</li>"
  1029. "<li>http://lv2plug.in/ns/extensions/ui</li>"
  1030. "<li>http://lv2plug.in/ns/extensions/units</li>"
  1031. #"<li>http://home.gna.org/lv2dynparam/v1</li>"
  1032. "<li>http://home.gna.org/lv2dynparam/rtmempool/v1</li>"
  1033. "<li>http://kxstudio.sf.net/ns/lv2ext/programs</li>"
  1034. #"<li>http://ll-plugins.nongnu.org/lv2/ext/midimap</li>"
  1035. "<li>http://ll-plugins.nongnu.org/lv2/ext/miditype</li>"
  1036. "<li>http://nedko.arnaudov.name/lv2/external_ui/</li>"
  1037. "</ul>"))
  1038. self.l_vst.setText(self.tr("<p>About 85&#37; complete (missing vst bank/presets and some minor stuff)</p>"))
  1039. # Single Plugin Parameter
  1040. class PluginParameter(QWidget, ui_carla_parameter.Ui_PluginParameter):
  1041. def __init__(self, parent, pinfo, plugin_id):
  1042. QWidget.__init__(self, parent)
  1043. self.setupUi(self)
  1044. self.ptype = pinfo['type']
  1045. self.parameter_id = pinfo['index']
  1046. self.hints = pinfo['hints']
  1047. self.midi_cc = -1
  1048. self.midi_channel = 1
  1049. self.plugin_id = plugin_id
  1050. self.add_MIDI_CCs_to_ComboBox()
  1051. self.label.setText(pinfo['name'])
  1052. if (self.ptype == PARAMETER_INPUT):
  1053. self.widget.set_minimum(pinfo['minimum'])
  1054. self.widget.set_maximum(pinfo['maximum'])
  1055. self.widget.set_default(pinfo['default'])
  1056. self.widget.set_value(pinfo['current'], False)
  1057. self.widget.set_label(pinfo['unit'])
  1058. self.widget.set_step(pinfo['step'])
  1059. self.widget.set_step_small(pinfo['step_small'])
  1060. self.widget.set_step_large(pinfo['step_large'])
  1061. self.widget.set_scalepoints(pinfo['scalepoints'], (pinfo['hints'] & PARAMETER_USES_SCALEPOINTS))
  1062. if (not self.hints & PARAMETER_IS_ENABLED):
  1063. self.widget.set_read_only(True)
  1064. self.combo.setEnabled(False)
  1065. self.sb_channel.setEnabled(False)
  1066. elif (not self.hints & PARAMETER_IS_AUTOMABLE):
  1067. self.combo.setEnabled(False)
  1068. self.sb_channel.setEnabled(False)
  1069. elif (self.ptype == PARAMETER_OUTPUT):
  1070. self.widget.set_minimum(pinfo['minimum'])
  1071. self.widget.set_maximum(pinfo['maximum'])
  1072. self.widget.set_value(pinfo['current'], False)
  1073. self.widget.set_label(pinfo['unit'])
  1074. self.widget.set_read_only(True)
  1075. if (not self.hints & PARAMETER_IS_AUTOMABLE):
  1076. self.combo.setEnabled(False)
  1077. self.sb_channel.setEnabled(False)
  1078. else:
  1079. self.widget.setVisible(False)
  1080. self.combo.setVisible(False)
  1081. self.sb_channel.setVisible(False)
  1082. self.set_parameter_midi_channel(pinfo['midi_channel'])
  1083. self.set_parameter_midi_cc(pinfo['midi_cc'])
  1084. self.connect(self.widget, SIGNAL("valueChanged(double)"), SLOT("slot_valueChanged(double)"))
  1085. self.connect(self.sb_channel, SIGNAL("valueChanged(int)"), SLOT("slot_midiChannelChanged(int)"))
  1086. self.connect(self.combo, SIGNAL("currentIndexChanged(int)"), SLOT("slot_midiCcChanged(int)"))
  1087. #if force_parameters_style:
  1088. #self.widget.force_plastique_style()
  1089. if (self.hints & PARAMETER_USES_CUSTOM_TEXT):
  1090. self.widget.set_text_call(self.textCallFunction)
  1091. self.widget.updateAll()
  1092. def set_default_value(self, value):
  1093. self.widget.set_default(value)
  1094. def set_parameter_value(self, value, send=True):
  1095. self.widget.set_value(value, send)
  1096. def set_parameter_midi_channel(self, channel):
  1097. self.midi_channel = channel
  1098. self.sb_channel.setValue(channel - 1)
  1099. def set_parameter_midi_cc(self, cc_index):
  1100. self.midi_cc = cc_index
  1101. self.set_MIDI_CC_in_ComboBox(cc_index)
  1102. def add_MIDI_CCs_to_ComboBox(self):
  1103. for MIDI_CC in MIDI_CC_LIST:
  1104. self.combo.addItem(MIDI_CC)
  1105. def set_MIDI_CC_in_ComboBox(self, midi_cc):
  1106. for i in range(len(MIDI_CC_LIST)):
  1107. midi_cc_text = MIDI_CC_LIST[i].split(" ")[0]
  1108. if (int(midi_cc_text, 16) == midi_cc):
  1109. cc_index = i
  1110. break
  1111. else:
  1112. cc_index = -1
  1113. cc_index += 1
  1114. self.combo.setCurrentIndex(cc_index)
  1115. def textCallFunction(self):
  1116. return cString(CarlaHost.get_parameter_text(self.plugin_id, self.parameter_id))
  1117. @pyqtSlot(float)
  1118. def slot_valueChanged(self, value):
  1119. self.emit(SIGNAL("valueChanged(int, double)"), self.parameter_id, value)
  1120. @pyqtSlot(int)
  1121. def slot_midiChannelChanged(self, channel):
  1122. if (self.midi_channel != channel):
  1123. self.emit(SIGNAL("midiChannelChanged(int, int)"), self.parameter_id, channel)
  1124. self.midi_channel = channel
  1125. @pyqtSlot(int)
  1126. def slot_midiCcChanged(self, cc_index):
  1127. if (cc_index <= 0):
  1128. midi_cc = -1
  1129. else:
  1130. midi_cc_text = MIDI_CC_LIST[cc_index - 1].split(" ")[0]
  1131. midi_cc = int(midi_cc_text, 16)
  1132. if (self.midi_cc != midi_cc):
  1133. self.emit(SIGNAL("midiCcChanged(int, int)"), self.parameter_id, midi_cc)
  1134. self.midi_cc = midi_cc
  1135. # Plugin GUI
  1136. class PluginGUI(QDialog):
  1137. def __init__(self, parent, plugin_name, resizable):
  1138. QDialog.__init__(self, parent)
  1139. self.myLayout = QVBoxLayout(self)
  1140. self.myLayout.setContentsMargins(0, 0, 0, 0)
  1141. self.setLayout(self.myLayout)
  1142. self.resizable = resizable
  1143. self.setNewSize(50, 50)
  1144. self.setWindowTitle("%s (GUI)" % (plugin_name))
  1145. def setNewSize(self, width, height):
  1146. if (width < 30):
  1147. width = 30
  1148. if (height < 30):
  1149. height = 30
  1150. if (self.resizable):
  1151. self.resize(width, height)
  1152. else:
  1153. self.setFixedSize(width, height)
  1154. def hideEvent(self, event):
  1155. # FIXME
  1156. event.accept()
  1157. self.close()
  1158. def done(self, r):
  1159. QDialog.done(self, r)
  1160. self.close()
  1161. # Plugin Editor (Built-in)
  1162. class PluginEdit(QDialog, ui_carla_edit.Ui_PluginEdit):
  1163. def __init__(self, parent, plugin_id):
  1164. QDialog.__init__(self, parent)
  1165. self.setupUi(self)
  1166. self.pinfo = None
  1167. self.ptype = PLUGIN_NONE
  1168. self.plugin_id = plugin_id
  1169. self.parameter_count = 0
  1170. self.parameter_list = [] # type, id, widget
  1171. self.parameter_list_to_update = [] # ids
  1172. self.state_filename = None
  1173. self.cur_program_index = -1
  1174. self.cur_midi_program_index = -1
  1175. self.tab_icon_off = QIcon(":/bitmaps/led_off.png")
  1176. self.tab_icon_on = QIcon(":/bitmaps/led_yellow.png")
  1177. self.tab_icon_count = 0
  1178. self.tab_icon_timers = []
  1179. self.connect(self.b_save_state, SIGNAL("clicked()"), SLOT("slot_saveState()"))
  1180. self.connect(self.b_load_state, SIGNAL("clicked()"), SLOT("slot_loadState()"))
  1181. self.connect(self.keyboard, SIGNAL("noteOn(int)"), SLOT("slot_noteOn(int)"))
  1182. self.connect(self.keyboard, SIGNAL("noteOff(int)"), SLOT("slot_noteOff(int)"))
  1183. self.connect(self.keyboard, SIGNAL("notesOn()"), SLOT("slot_notesOn()"))
  1184. self.connect(self.keyboard, SIGNAL("notesOff()"), SLOT("slot_notesOff()"))
  1185. self.connect(self.cb_programs, SIGNAL("currentIndexChanged(int)"), SLOT("slot_programIndexChanged(int)"))
  1186. self.connect(self.cb_midi_programs, SIGNAL("currentIndexChanged(int)"), SLOT("slot_midiProgramIndexChanged(int)"))
  1187. self.keyboard.setMode(self.keyboard.HORIZONTAL)
  1188. self.keyboard.setOctaves(6)
  1189. self.scrollArea.ensureVisible(self.keyboard.width() * 1 / 5, 0)
  1190. self.scrollArea.setVisible(False)
  1191. # TODO - not implemented yet
  1192. self.b_reload_program.setEnabled(False)
  1193. self.b_reload_midi_program.setEnabled(False)
  1194. self.do_reload_all()
  1195. def set_parameter_to_update(self, parameter_id):
  1196. if (parameter_id not in self.parameter_list_to_update):
  1197. self.parameter_list_to_update.append(parameter_id)
  1198. def set_parameter_midi_channel(self, parameter_id, channel):
  1199. for ptype, pid, pwidget in self.parameter_list:
  1200. if (pid == parameter_id):
  1201. pwidget.set_parameter_midi_channel(channel)
  1202. break
  1203. def set_parameter_midi_cc(self, parameter_id, midi_cc):
  1204. for ptype, pid, pwidget in self.parameter_list:
  1205. if (pid == parameter_id):
  1206. pwidget.set_parameter_midi_cc(midi_cc)
  1207. break
  1208. def set_program(self, program_id):
  1209. self.cur_program_index = program_id
  1210. self.cb_programs.setCurrentIndex(program_id)
  1211. QTimer.singleShot(0, self, SLOT("slot_checkInputControlParameters()"))
  1212. def set_midi_program(self, midi_program_id):
  1213. self.cur_midi_program_index = midi_program_id
  1214. self.cb_midi_programs.setCurrentIndex(midi_program_id)
  1215. QTimer.singleShot(0, self, SLOT("slot_checkInputControlParameters()"))
  1216. def do_update(self):
  1217. # Update current program text
  1218. if (self.cb_programs.count() > 0):
  1219. pindex = self.cb_programs.currentIndex()
  1220. pname = cString(CarlaHost.get_program_name(self.plugin_id, pindex))
  1221. self.cb_programs.setItemText(pindex, pname)
  1222. # Update current midi program text
  1223. if (self.cb_midi_programs.count() > 0):
  1224. mpindex = self.cb_midi_programs.currentIndex()
  1225. mpname = "%s %s" % (self.cb_midi_programs.currentText().split(" ", 1)[0], cString(CarlaHost.get_midi_program_name(self.plugin_id, mpindex)))
  1226. self.cb_midi_programs.setItemText(mpindex, mpname)
  1227. QTimer.singleShot(0, self, SLOT("slot_checkInputControlParameters()"))
  1228. QTimer.singleShot(0, self, SLOT("slot_checkOutputControlParameters()"))
  1229. def do_reload_all(self):
  1230. self.pinfo = CarlaHost.get_plugin_info(self.plugin_id)
  1231. if (self.pinfo['valid']):
  1232. self.pinfo["binary"] = cString(self.pinfo["binary"])
  1233. self.pinfo["name"] = cString(self.pinfo["name"])
  1234. self.pinfo["label"] = cString(self.pinfo["label"])
  1235. self.pinfo["maker"] = cString(self.pinfo["maker"])
  1236. self.pinfo["copyright"] = cString(self.pinfo["copyright"])
  1237. else:
  1238. self.pinfo["type"] = PLUGIN_NONE
  1239. self.pinfo["category"] = PLUGIN_CATEGORY_NONE
  1240. self.pinfo["hints"] = 0x0
  1241. self.pinfo["binary"] = ""
  1242. self.pinfo["name"] = "(Unknown)"
  1243. self.pinfo["label"] = ""
  1244. self.pinfo["maker"] = ""
  1245. self.pinfo["copyright"] = ""
  1246. self.pinfo["unique_id"] = 0
  1247. self.do_reload_info()
  1248. self.do_reload_parameters()
  1249. self.do_reload_programs()
  1250. def do_reload_info(self):
  1251. if self.ptype == PLUGIN_NONE and self.pinfo['type'] in (PLUGIN_DSSI, PLUGIN_LV2, PLUGIN_GIG, PLUGIN_SF2, PLUGIN_SFZ):
  1252. self.tab_programs.setCurrentIndex(1)
  1253. self.ptype = self.pinfo['type']
  1254. real_plugin_name = cString(CarlaHost.get_real_plugin_name(self.plugin_id))
  1255. self.le_name.setText(real_plugin_name)
  1256. self.le_name.setToolTip(real_plugin_name)
  1257. self.le_label.setText(self.pinfo['label'])
  1258. self.le_label.setToolTip(self.pinfo['label'])
  1259. self.le_maker.setText(self.pinfo['maker'])
  1260. self.le_maker.setToolTip(self.pinfo['maker'])
  1261. self.le_copyright.setText(self.pinfo['copyright'])
  1262. self.le_copyright.setToolTip(self.pinfo['copyright'])
  1263. self.le_unique_id.setText(str(self.pinfo['unique_id']))
  1264. self.le_unique_id.setToolTip(str(self.pinfo['unique_id']))
  1265. self.label_plugin.setText("\n%s\n" % (self.pinfo['name']))
  1266. self.setWindowTitle(self.pinfo['name'])
  1267. if self.ptype == PLUGIN_LADSPA:
  1268. self.le_type.setText("LADSPA")
  1269. elif self.ptype == PLUGIN_DSSI:
  1270. self.le_type.setText("DSSI")
  1271. elif self.ptype == PLUGIN_LV2:
  1272. self.le_type.setText("LV2")
  1273. elif self.ptype == PLUGIN_VST:
  1274. self.le_type.setText("VST")
  1275. elif self.ptype == PLUGIN_GIG:
  1276. self.le_type.setText("GIG")
  1277. elif self.ptype == PLUGIN_SF2:
  1278. self.le_type.setText("SF2")
  1279. elif self.ptype == PLUGIN_SFZ:
  1280. self.le_type.setText("SFZ")
  1281. else:
  1282. self.le_type.setText(self.tr("Unknown"))
  1283. audio_count = CarlaHost.get_audio_port_count_info(self.plugin_id)
  1284. if (not audio_count['valid']):
  1285. audio_count['ins'] = 0
  1286. audio_count['outs'] = 0
  1287. audio_count['total'] = 0
  1288. midi_count = CarlaHost.get_midi_port_count_info(self.plugin_id)
  1289. if (not midi_count['valid']):
  1290. midi_count['ins'] = 0
  1291. midi_count['outs'] = 0
  1292. midi_count['total'] = 0
  1293. param_count = CarlaHost.get_parameter_count_info(self.plugin_id)
  1294. if (not param_count['valid']):
  1295. param_count['ins'] = 0
  1296. param_count['outs'] = 0
  1297. param_count['total'] = 0
  1298. self.le_ains.setText(str(audio_count['ins']))
  1299. self.le_aouts.setText(str(audio_count['outs']))
  1300. self.le_params.setText(str(param_count['ins']))
  1301. self.le_couts.setText(str(param_count['outs']))
  1302. self.le_is_synth.setText(self.tr("Yes") if (self.pinfo['hints'] & PLUGIN_IS_SYNTH) else (self.tr("No")))
  1303. self.le_has_gui.setText(self.tr("Yes") if (self.pinfo['hints'] & PLUGIN_HAS_GUI) else (self.tr("No")))
  1304. self.scrollArea.setVisible(self.pinfo['hints'] & PLUGIN_IS_SYNTH or (midi_count['ins'] > 0 < midi_count['outs']))
  1305. self.parent().recheck_hints(self.pinfo['hints'])
  1306. def do_reload_parameters(self):
  1307. parameters_count = CarlaHost.get_parameter_count(self.plugin_id)
  1308. self.parameter_list = []
  1309. self.parameter_list_to_update = []
  1310. self.tab_icon_count = 0
  1311. self.tab_icon_timers = []
  1312. for i in range(self.tabWidget.count()):
  1313. if (i == 0): continue
  1314. self.tabWidget.widget(1).deleteLater()
  1315. self.tabWidget.removeTab(1)
  1316. if (parameters_count <= 0):
  1317. pass
  1318. elif (parameters_count <= MAX_PARAMETERS):
  1319. p_in = []
  1320. p_in_tmp = []
  1321. p_in_index = 0
  1322. p_in_width = 0
  1323. p_out = []
  1324. p_out_tmp = []
  1325. p_out_index = 0
  1326. p_out_width = 0
  1327. for i in range(parameters_count):
  1328. param_info = CarlaHost.get_parameter_info(self.plugin_id, i)
  1329. param_data = CarlaHost.get_parameter_data(self.plugin_id, i)
  1330. param_ranges = CarlaHost.get_parameter_ranges(self.plugin_id, i)
  1331. if not param_info['valid']:
  1332. continue
  1333. parameter = {
  1334. 'type': param_data['type'],
  1335. 'hints': param_data['hints'],
  1336. 'name': cString(param_info['name']),
  1337. 'unit': cString(param_info['unit']),
  1338. 'scalepoints': [],
  1339. 'index': param_data['index'],
  1340. 'default': param_ranges['def'],
  1341. 'minimum': param_ranges['min'],
  1342. 'maximum': param_ranges['max'],
  1343. 'step': param_ranges['step'],
  1344. 'step_small': param_ranges['step_small'],
  1345. 'step_large': param_ranges['step_large'],
  1346. 'midi_channel': param_data['midi_channel'],
  1347. 'midi_cc': param_data['midi_cc'],
  1348. 'current': CarlaHost.get_current_parameter_value(self.plugin_id, i)
  1349. }
  1350. for j in range(param_info['scalepoint_count']):
  1351. scalepoint = CarlaHost.get_scalepoint_info(self.plugin_id, i, j)
  1352. parameter['scalepoints'].append({
  1353. 'value': scalepoint['value'],
  1354. 'label': cString(scalepoint['label'])
  1355. })
  1356. # -----------------------------------------------------------------
  1357. # Get width values, in packs of 10
  1358. if (parameter['type'] == PARAMETER_INPUT):
  1359. p_in_tmp.append(parameter)
  1360. p_in_width_tmp = QFontMetrics(self.font()).width(parameter['name'])
  1361. if (p_in_width_tmp > p_in_width):
  1362. p_in_width = p_in_width_tmp
  1363. if (len(p_in_tmp) == 10):
  1364. p_in.append((p_in_tmp, p_in_width))
  1365. p_in_tmp = []
  1366. p_in_index = 0
  1367. p_in_width = 0
  1368. else:
  1369. p_in_index += 1
  1370. elif (parameter['type'] == PARAMETER_OUTPUT):
  1371. p_out_tmp.append(parameter)
  1372. p_out_width_tmp = QFontMetrics(self.font()).width(parameter['name'])
  1373. if (p_out_width_tmp > p_out_width):
  1374. p_out_width = p_out_width_tmp
  1375. if (len(p_out_tmp) == 10):
  1376. p_out.append((p_out_tmp, p_out_width))
  1377. p_out_tmp = []
  1378. p_out_index = 0
  1379. p_out_width = 0
  1380. else:
  1381. p_out_index += 1
  1382. else:
  1383. # Final page width values
  1384. if (0 < len(p_in_tmp) < 10):
  1385. p_in.append((p_in_tmp, p_in_width))
  1386. if (0 < len(p_out_tmp) < 10):
  1387. p_out.append((p_out_tmp, p_out_width))
  1388. # -----------------------------------------------------------------
  1389. # Create parameter widgets
  1390. if (len(p_in) > 0):
  1391. self.createParameterWidgets(p_in, self.tr("Parameters"), PARAMETER_INPUT)
  1392. if (len(p_out) > 0):
  1393. self.createParameterWidgets(p_out, self.tr("Outputs"), PARAMETER_OUTPUT)
  1394. else: # > MAX_PARAMETERS
  1395. fake_name = "This plugin has too many parameters to display here!"
  1396. p_fake = []
  1397. p_fake_tmp = []
  1398. p_fake_width = QFontMetrics(self.font()).width(fake_name)
  1399. parameter = {
  1400. 'type': PARAMETER_UNKNOWN,
  1401. 'hints': 0,
  1402. 'name': fake_name,
  1403. 'unit': "",
  1404. 'scalepoints': [],
  1405. 'index': 0,
  1406. 'default': 0,
  1407. 'minimum': 0,
  1408. 'maximum': 0,
  1409. 'step': 0,
  1410. 'step_small': 0,
  1411. 'step_large': 0,
  1412. 'midi_channel': 0,
  1413. 'midi_cc': -1,
  1414. 'current': 0.0
  1415. }
  1416. p_fake_tmp.append(parameter)
  1417. p_fake.append((p_fake_tmp, p_fake_width))
  1418. self.createParameterWidgets(p_fake, self.tr("Information"), PARAMETER_UNKNOWN)
  1419. def do_reload_programs(self):
  1420. # Programs
  1421. self.cb_programs.blockSignals(True)
  1422. self.cb_programs.clear()
  1423. program_count = CarlaHost.get_program_count(self.plugin_id)
  1424. if (program_count > 0):
  1425. self.cb_programs.setEnabled(True)
  1426. for i in range(program_count):
  1427. pname = cString(CarlaHost.get_program_name(self.plugin_id, i))
  1428. self.cb_programs.addItem(pname)
  1429. self.cur_program_index = CarlaHost.get_current_program_index(self.plugin_id)
  1430. self.cb_programs.setCurrentIndex(self.cur_program_index)
  1431. else:
  1432. self.cb_programs.setEnabled(False)
  1433. self.cb_programs.blockSignals(False)
  1434. # MIDI Programs
  1435. self.cb_midi_programs.blockSignals(True)
  1436. self.cb_midi_programs.clear()
  1437. midi_program_count = CarlaHost.get_midi_program_count(self.plugin_id)
  1438. if (midi_program_count > 0):
  1439. self.cb_midi_programs.setEnabled(True)
  1440. for i in range(midi_program_count):
  1441. midip = CarlaHost.get_midi_program_info(self.plugin_id, i)
  1442. bank = int(midip['bank'])
  1443. prog = int(midip['program'])
  1444. label = cString(midip['label'])
  1445. self.cb_midi_programs.addItem("%03i:%03i - %s" % (bank, prog, label))
  1446. self.cur_midi_program_index = CarlaHost.get_current_midi_program_index(self.plugin_id)
  1447. self.cb_midi_programs.setCurrentIndex(self.cur_midi_program_index)
  1448. else:
  1449. self.cb_midi_programs.setEnabled(False)
  1450. self.cb_midi_programs.blockSignals(False)
  1451. def saveState_InternalFormat(self):
  1452. content = ("<?xml version='1.0' encoding='UTF-8'?>\n"
  1453. "<!DOCTYPE CARLA-PRESET>\n"
  1454. "<CARLA-PRESET VERSION='%s'>\n") % (VERSION)
  1455. content += self.parent().getSaveXMLContent()
  1456. content += "</CARLA-PRESET>\n"
  1457. try:
  1458. open(self.state_filename, "w").write(content)
  1459. except:
  1460. QMessageBox.critical(self, self.tr("Error"), self.tr("Failed to save state file"))
  1461. def saveState_Lv2Format(self):
  1462. pass
  1463. def saveState_VstFormat(self):
  1464. pass
  1465. def loadState_InternalFormat(self):
  1466. try:
  1467. state_read = open(self.state_filename, "r").read()
  1468. except:
  1469. QMessageBox.critical(self, self.tr("Error"), self.tr("Failed to load state file"))
  1470. return
  1471. xml = QDomDocument()
  1472. xml.setContent(state_read)
  1473. xml_node = xml.documentElement()
  1474. if (xml_node.tagName() != "CARLA-PRESET"):
  1475. QMessageBox.critical(self, self.tr("Error"), self.tr("Not a valid Carla state file"))
  1476. return
  1477. x_save_state_dict = getStateDictFromXML(xml_node)
  1478. self.parent().loadStateDict(x_save_state_dict)
  1479. def createParameterWidgets(self, p_list_full, tab_name, ptype):
  1480. for i in range(len(p_list_full)):
  1481. p_list = p_list_full[i][0]
  1482. width = p_list_full[i][1]
  1483. if (len(p_list) > 0):
  1484. container = QWidget(self.tabWidget)
  1485. layout = QVBoxLayout(container)
  1486. container.setLayout(layout)
  1487. for j in range(len(p_list)):
  1488. pwidget = PluginParameter(container, p_list[j], self.plugin_id)
  1489. pwidget.label.setMinimumWidth(width)
  1490. pwidget.label.setMaximumWidth(width)
  1491. pwidget.tab_index = self.tabWidget.count()
  1492. layout.addWidget(pwidget)
  1493. self.parameter_list.append((ptype, p_list[j]['index'], pwidget))
  1494. if (ptype == PARAMETER_INPUT):
  1495. self.connect(pwidget, SIGNAL("valueChanged(int, double)"), SLOT("slot_parameterValueChanged(int, double)"))
  1496. self.connect(pwidget, SIGNAL("midiChannelChanged(int, int)"), SLOT("slot_parameterMidiChannelChanged(int, int)"))
  1497. self.connect(pwidget, SIGNAL("midiCcChanged(int, int)"), SLOT("slot_parameterMidiCcChanged(int, int)"))
  1498. # FIXME
  1499. layout.addStretch()
  1500. self.tabWidget.addTab(container, "%s (%i)" % (tab_name, i + 1))
  1501. if (ptype == PARAMETER_INPUT):
  1502. self.tabWidget.setTabIcon(pwidget.tab_index, self.tab_icon_off)
  1503. self.tab_icon_timers.append(ICON_STATE_NULL)
  1504. def animateTab(self, index):
  1505. if (self.tab_icon_timers[index - 1] == ICON_STATE_NULL):
  1506. self.tabWidget.setTabIcon(index, self.tab_icon_on)
  1507. self.tab_icon_timers[index - 1] = ICON_STATE_ON
  1508. def check_gui_stuff(self):
  1509. # Check Tab icons
  1510. for i in range(len(self.tab_icon_timers)):
  1511. if (self.tab_icon_timers[i] == ICON_STATE_ON):
  1512. self.tab_icon_timers[i] = ICON_STATE_WAIT
  1513. elif (self.tab_icon_timers[i] == ICON_STATE_WAIT):
  1514. self.tab_icon_timers[i] = ICON_STATE_OFF
  1515. elif (self.tab_icon_timers[i] == ICON_STATE_OFF):
  1516. self.tabWidget.setTabIcon(i + 1, self.tab_icon_off)
  1517. self.tab_icon_timers[i] = ICON_STATE_NULL
  1518. # Check parameters needing update
  1519. for parameter_id in self.parameter_list_to_update:
  1520. value = CarlaHost.get_current_parameter_value(self.plugin_id, parameter_id)
  1521. for ptype, pid, pwidget in self.parameter_list:
  1522. if (pid == parameter_id):
  1523. pwidget.set_parameter_value(value, False)
  1524. if (ptype == PARAMETER_INPUT):
  1525. self.animateTab(pwidget.tab_index)
  1526. break
  1527. # Clear all parameters
  1528. self.parameter_list_to_update = []
  1529. # Update output parameters
  1530. QTimer.singleShot(0, self, SLOT("slot_checkOutputControlParameters()"))
  1531. @pyqtSlot()
  1532. def slot_saveState(self):
  1533. # TODO - LV2 and VST native formats
  1534. if (self.state_filename):
  1535. ask_try = QMessageBox.question(self, self.tr("Overwrite?"), self.tr("Overwrite previously created file?"), QMessageBox.Ok|QMessageBox.Cancel)
  1536. if (ask_try == QMessageBox.Ok):
  1537. self.saveState_InternalFormat()
  1538. else:
  1539. self.state_filename = None
  1540. self.slot_saveState()
  1541. else:
  1542. file_filter = self.tr("Carla State File (*.carxs)")
  1543. filename_try = QFileDialog.getSaveFileName(self, self.tr("Save Carla State File"), filter=file_filter)
  1544. if (filename_try):
  1545. self.state_filename = filename_try
  1546. self.saveState_InternalFormat()
  1547. @pyqtSlot()
  1548. def slot_loadState(self):
  1549. # TODO - LV2 and VST native formats
  1550. file_filter = self.tr("Carla State File (*.carxs)")
  1551. filename_try = QFileDialog.getOpenFileName(self, self.tr("Open Carla State File"), filter=file_filter)
  1552. if (filename_try):
  1553. self.state_filename = filename_try
  1554. self.loadState_InternalFormat()
  1555. @pyqtSlot(int, float)
  1556. def slot_parameterValueChanged(self, parameter_id, value):
  1557. CarlaHost.set_parameter_value(self.plugin_id, parameter_id, value)
  1558. @pyqtSlot(int, int)
  1559. def slot_parameterMidiChannelChanged(self, parameter_id, channel):
  1560. CarlaHost.set_parameter_midi_channel(self.plugin_id, parameter_id, channel - 1)
  1561. @pyqtSlot(int, int)
  1562. def slot_parameterMidiCcChanged(self, parameter_id, cc_index):
  1563. CarlaHost.set_parameter_midi_cc(self.plugin_id, parameter_id, cc_index)
  1564. @pyqtSlot(int)
  1565. def slot_programIndexChanged(self, index):
  1566. if (self.cur_program_index != index):
  1567. CarlaHost.set_program(self.plugin_id, index)
  1568. QTimer.singleShot(0, self, SLOT("slot_checkInputControlParameters()"))
  1569. self.cur_program_index = index
  1570. @pyqtSlot(int)
  1571. def slot_midiProgramIndexChanged(self, index):
  1572. if (self.cur_midi_program_index != index):
  1573. CarlaHost.set_midi_program(self.plugin_id, index)
  1574. QTimer.singleShot(0, self, SLOT("slot_checkInputControlParameters()"))
  1575. self.cur_midi_program_index = index
  1576. @pyqtSlot(int)
  1577. def slot_noteOn(self, note):
  1578. CarlaHost.send_midi_note(self.plugin_id, True, note, 100)
  1579. @pyqtSlot(int)
  1580. def slot_noteOff(self, note):
  1581. CarlaHost.send_midi_note(self.plugin_id, False, note, 0)
  1582. @pyqtSlot()
  1583. def slot_notesOn(self):
  1584. self.parent().led_midi.setChecked(True)
  1585. @pyqtSlot()
  1586. def slot_notesOff(self):
  1587. self.parent().led_midi.setChecked(False)
  1588. @pyqtSlot()
  1589. def slot_checkInputControlParameters(self):
  1590. for ptype, pid, pwidget in self.parameter_list:
  1591. if ptype == PARAMETER_INPUT:
  1592. if self.pinfo["type"] not in (PLUGIN_GIG, PLUGIN_SF2, PLUGIN_SFZ):
  1593. pwidget.set_default_value(CarlaHost.get_default_parameter_value(self.plugin_id, pid))
  1594. pwidget.set_parameter_value(CarlaHost.get_current_parameter_value(self.plugin_id, pid), False)
  1595. @pyqtSlot()
  1596. def slot_checkOutputControlParameters(self):
  1597. for ptype, pid, pwidget in self.parameter_list:
  1598. if (ptype == PARAMETER_OUTPUT):
  1599. pwidget.set_parameter_value(CarlaHost.get_current_parameter_value(self.plugin_id, pid), False)
  1600. # (New) Plugin Widget
  1601. class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget):
  1602. def __init__(self, parent, plugin_id):
  1603. QFrame.__init__(self, parent)
  1604. self.setupUi(self)
  1605. self.plugin_id = plugin_id
  1606. self.params_total = 0
  1607. self.parameter_activity_timer = None
  1608. self.last_led_ain_state = False
  1609. self.last_led_aout_state = False
  1610. # Fake effect
  1611. self.color_1 = QColor(0, 0, 0, 220)
  1612. self.color_2 = QColor(0, 0, 0, 170)
  1613. self.color_3 = QColor(7, 7, 7, 250)
  1614. self.color_4 = QColor(14, 14, 14, 255)
  1615. self.led_enable.setColor(self.led_enable.BIG_RED)
  1616. self.led_enable.setChecked(False)
  1617. self.led_control.setColor(self.led_control.YELLOW)
  1618. self.led_control.setEnabled(False)
  1619. self.led_midi.setColor(self.led_midi.RED)
  1620. self.led_midi.setEnabled(False)
  1621. self.led_audio_in.setColor(self.led_audio_in.GREEN)
  1622. self.led_audio_in.setEnabled(False)
  1623. self.led_audio_out.setColor(self.led_audio_out.BLUE)
  1624. self.led_audio_out.setEnabled(False)
  1625. self.dial_drywet.setPixmap(3)
  1626. self.dial_vol.setPixmap(3)
  1627. self.dial_b_left.setPixmap(4)
  1628. self.dial_b_right.setPixmap(4)
  1629. #self.dial_drywet.setLabel("Wet")
  1630. #self.dial_vol.setLabel("Vol")
  1631. #self.dial_b_left.setLabel("L")
  1632. #self.dial_b_right.setLabel("R")
  1633. self.dial_drywet.setCustomPaint(self.dial_b_left.CUSTOM_PAINT_CARLA_WET)
  1634. self.dial_vol.setCustomPaint(self.dial_b_right.CUSTOM_PAINT_CARLA_VOL)
  1635. self.dial_b_left.setCustomPaint(self.dial_b_left.CUSTOM_PAINT_CARLA_L)
  1636. self.dial_b_right.setCustomPaint(self.dial_b_right.CUSTOM_PAINT_CARLA_R)
  1637. self.peak_in.setColor(self.peak_in.GREEN)
  1638. self.peak_in.setOrientation(self.peak_in.HORIZONTAL)
  1639. self.peak_out.setColor(self.peak_in.BLUE)
  1640. self.peak_out.setOrientation(self.peak_out.HORIZONTAL)
  1641. audio_count = CarlaHost.get_audio_port_count_info(self.plugin_id)
  1642. if (not audio_count['valid']):
  1643. audio_count['ins'] = 0
  1644. audio_count['outs'] = 0
  1645. audio_count['total'] = 0
  1646. self.peaks_in = int(audio_count['ins'])
  1647. self.peaks_out = int(audio_count['outs'])
  1648. if self.peaks_in > 2:
  1649. self.peaks_in = 2
  1650. if self.peaks_out > 2:
  1651. self.peaks_out = 2
  1652. self.peak_in.setChannels(self.peaks_in)
  1653. self.peak_out.setChannels(self.peaks_out)
  1654. self.pinfo = CarlaHost.get_plugin_info(self.plugin_id)
  1655. if (self.pinfo['valid']):
  1656. self.pinfo["binary"] = cString(self.pinfo["binary"])
  1657. self.pinfo["name"] = cString(self.pinfo["name"])
  1658. self.pinfo["label"] = cString(self.pinfo["label"])
  1659. self.pinfo["maker"] = cString(self.pinfo["maker"])
  1660. self.pinfo["copyright"] = cString(self.pinfo["copyright"])
  1661. else:
  1662. self.pinfo["type"] = PLUGIN_NONE
  1663. self.pinfo["category"] = PLUGIN_CATEGORY_NONE
  1664. self.pinfo["hints"] = 0
  1665. self.pinfo["binary"] = ""
  1666. self.pinfo["name"] = "(Unknown)"
  1667. self.pinfo["label"] = ""
  1668. self.pinfo["maker"] = ""
  1669. self.pinfo["copyright"] = ""
  1670. self.pinfo["unique_id"] = 0
  1671. # Set widget page
  1672. if (self.pinfo['type'] == PLUGIN_NONE or audio_count['total'] == 0):
  1673. self.stackedWidget.setCurrentIndex(1)
  1674. else:
  1675. self.stackedWidget.setCurrentIndex(0)
  1676. self.label_name.setText(self.pinfo['name'])
  1677. # Enable/disable features
  1678. self.recheck_hints(self.pinfo['hints'])
  1679. # Colorify
  1680. if (self.pinfo['category'] == PLUGIN_CATEGORY_SYNTH):
  1681. self.setWidgetColor(PALETTE_COLOR_WHITE)
  1682. elif (self.pinfo['category'] == PLUGIN_CATEGORY_DELAY):
  1683. self.setWidgetColor(PALETTE_COLOR_ORANGE)
  1684. elif (self.pinfo['category'] == PLUGIN_CATEGORY_EQ):
  1685. self.setWidgetColor(PALETTE_COLOR_GREEN)
  1686. elif (self.pinfo['category'] == PLUGIN_CATEGORY_FILTER):
  1687. self.setWidgetColor(PALETTE_COLOR_BLUE)
  1688. elif (self.pinfo['category'] == PLUGIN_CATEGORY_DYNAMICS):
  1689. self.setWidgetColor(PALETTE_COLOR_PINK)
  1690. elif (self.pinfo['category'] == PLUGIN_CATEGORY_MODULATOR):
  1691. self.setWidgetColor(PALETTE_COLOR_RED)
  1692. elif (self.pinfo['category'] == PLUGIN_CATEGORY_UTILITY):
  1693. self.setWidgetColor(PALETTE_COLOR_YELLOW)
  1694. elif (self.pinfo['category'] == PLUGIN_CATEGORY_OTHER):
  1695. self.setWidgetColor(PALETTE_COLOR_BROWN)
  1696. else:
  1697. self.setWidgetColor(PALETTE_COLOR_NONE)
  1698. if self.pinfo['hints'] & PLUGIN_IS_SYNTH:
  1699. self.led_audio_in.setVisible(False)
  1700. else:
  1701. self.led_midi.setVisible(False)
  1702. self.edit_dialog = PluginEdit(self, self.plugin_id)
  1703. self.edit_dialog.hide()
  1704. self.edit_dialog_geometry = None
  1705. if self.pinfo['hints'] & PLUGIN_HAS_GUI:
  1706. gui_info = CarlaHost.get_gui_info(self.plugin_id)
  1707. self.gui_dialog_type = gui_info['type']
  1708. if (self.gui_dialog_type in (GUI_INTERNAL_QT4, GUI_INTERNAL_X11)):
  1709. self.gui_dialog = None
  1710. self.gui_dialog = PluginGUI(self, self.pinfo['name'], gui_info['resizable'])
  1711. self.gui_dialog.hide()
  1712. self.gui_dialog_geometry = None
  1713. self.connect(self.gui_dialog, SIGNAL("finished(int)"), SLOT("slot_guiClosed()"))
  1714. # TODO - display
  1715. CarlaHost.set_gui_data(self.plugin_id, 0, unwrapinstance(self.gui_dialog))
  1716. elif self.gui_dialog_type in (GUI_EXTERNAL_OSC, GUI_EXTERNAL_LV2):
  1717. self.gui_dialog = None
  1718. else:
  1719. self.gui_dialog = None
  1720. self.gui_dialog_type = GUI_NONE
  1721. self.b_gui.setEnabled(False)
  1722. else:
  1723. self.gui_dialog = None
  1724. self.gui_dialog_type = GUI_NONE
  1725. self.connect(self.led_enable, SIGNAL("clicked(bool)"), SLOT("slot_setActive(bool)"))
  1726. self.connect(self.dial_drywet, SIGNAL("sliderMoved(int)"), SLOT("slot_setDryWet(int)"))
  1727. self.connect(self.dial_vol, SIGNAL("sliderMoved(int)"), SLOT("slot_setVolume(int)"))
  1728. self.connect(self.dial_b_left, SIGNAL("sliderMoved(int)"), SLOT("slot_setBalanceLeft(int)"))
  1729. self.connect(self.dial_b_right, SIGNAL("sliderMoved(int)"), SLOT("slot_setBalanceRight(int)"))
  1730. self.connect(self.b_gui, SIGNAL("clicked(bool)"), SLOT("slot_guiClicked(bool)"))
  1731. self.connect(self.b_edit, SIGNAL("clicked(bool)"), SLOT("slot_editClicked(bool)"))
  1732. self.connect(self.b_remove, SIGNAL("clicked()"), SLOT("slot_removeClicked()"))
  1733. self.connect(self.dial_drywet, SIGNAL("customContextMenuRequested(QPoint)"), SLOT("slot_showCustomDialMenu()"))
  1734. self.connect(self.dial_vol, SIGNAL("customContextMenuRequested(QPoint)"), SLOT("slot_showCustomDialMenu()"))
  1735. self.connect(self.dial_b_left, SIGNAL("customContextMenuRequested(QPoint)"), SLOT("slot_showCustomDialMenu()"))
  1736. self.connect(self.dial_b_right, SIGNAL("customContextMenuRequested(QPoint)"), SLOT("slot_showCustomDialMenu()"))
  1737. self.connect(self.edit_dialog, SIGNAL("finished(int)"), SLOT("slot_editClosed()"))
  1738. self.check_gui_stuff()
  1739. def set_active(self, active, gui_send=False, callback_send=True):
  1740. if gui_send: self.led_enable.setChecked(active)
  1741. if callback_send: CarlaHost.set_active(self.plugin_id, active)
  1742. def set_drywet(self, value, gui_send=False, callback_send=True):
  1743. if gui_send: self.dial_drywet.setValue(value)
  1744. if callback_send: CarlaHost.set_drywet(self.plugin_id, float(value) / 1000)
  1745. message = self.tr("Output dry/wet (%s%%)" % (value / 10))
  1746. self.dial_drywet.setStatusTip(message)
  1747. gui.statusBar().showMessage(message)
  1748. def set_volume(self, value, gui_send=False, callback_send=True):
  1749. if gui_send: self.dial_vol.setValue(value)
  1750. if callback_send: CarlaHost.set_volume(self.plugin_id, float(value) / 1000)
  1751. message = self.tr("Output volume (%s%%)" % (value / 10))
  1752. self.dial_vol.setStatusTip(message)
  1753. gui.statusBar().showMessage(message)
  1754. def set_balance_left(self, value, gui_send=False, callback_send=True):
  1755. if gui_send: self.dial_b_left.setValue(value)
  1756. if callback_send: CarlaHost.set_balance_left(self.plugin_id, float(value) / 1000)
  1757. if value == 0:
  1758. message = self.tr("Left Panning (Center)")
  1759. elif value < 0:
  1760. message = self.tr("Left Panning (%s%% Left)" % (-value / 10))
  1761. else:
  1762. message = self.tr("Left Panning (%s%% Right)" % (value / 10))
  1763. self.dial_b_left.setStatusTip(message)
  1764. gui.statusBar().showMessage(message)
  1765. def set_balance_right(self, value, gui_send=False, callback_send=True):
  1766. if gui_send: self.dial_b_right.setValue(value)
  1767. if callback_send: CarlaHost.set_balance_right(self.plugin_id, float(value) / 1000)
  1768. if value == 0:
  1769. message = self.tr("Right Panning (Center)")
  1770. elif value < 0:
  1771. message = self.tr("Right Panning (%s%% Left)" % (-value / 10))
  1772. else:
  1773. message = self.tr("Right Panning (%s%% Right)" % (value / 10))
  1774. self.dial_b_right.setStatusTip(message)
  1775. gui.statusBar().showMessage(message)
  1776. def setWidgetColor(self, color):
  1777. if (color == PALETTE_COLOR_WHITE):
  1778. r = 110
  1779. g = 110
  1780. b = 110
  1781. elif (color == PALETTE_COLOR_RED):
  1782. r = 110
  1783. g = 15
  1784. b = 15
  1785. elif (color == PALETTE_COLOR_GREEN):
  1786. r = 15
  1787. g = 110
  1788. b = 15
  1789. elif (color == PALETTE_COLOR_BLUE):
  1790. r = 15
  1791. g = 15
  1792. b = 110
  1793. elif (color == PALETTE_COLOR_YELLOW):
  1794. r = 110
  1795. g = 110
  1796. b = 15
  1797. elif (color == PALETTE_COLOR_ORANGE):
  1798. r = 180
  1799. g = 110
  1800. b = 15
  1801. elif (color == PALETTE_COLOR_BROWN):
  1802. r = 110
  1803. g = 35
  1804. b = 15
  1805. elif (color == PALETTE_COLOR_PINK):
  1806. r = 110
  1807. g = 15
  1808. b = 110
  1809. else:
  1810. r = 35
  1811. g = 35
  1812. b = 35
  1813. border_r = (r*2/3)+36
  1814. border_g = (g*2/3)+36
  1815. border_b = (b*2/3)+36
  1816. self.setStyleSheet("""
  1817. QFrame#PluginWidget {
  1818. background-image: url(:/bitmaps/textures/metal_9-512px.jpg);
  1819. background-color: rgb(17, 17, 17);
  1820. background-repeat: repeat-x;
  1821. background-position: top left;
  1822. }
  1823. QLabel#label_name {
  1824. color: white;
  1825. }
  1826. QWidget#widget_buttons {
  1827. background-color: rgb(%i, %i, %i);
  1828. border-left: 1px solid rgb(%i, %i, %i);
  1829. border-right: 1px solid rgb(%i, %i, %i);
  1830. border-bottom: 1px solid rgb(%i, %i, %i);
  1831. border-bottom-left-radius: 3px;
  1832. border-bottom-right-radius: 3px;
  1833. }
  1834. QPushButton#b_gui:hover, QPushButton#b_edit:hover, QPushButton#b_remove:hover {
  1835. background-color: rgb(%i, %i, %i);
  1836. border: 1px solid rgb(%i, %i, %i);
  1837. border-radius: 3px;
  1838. }
  1839. QFrame#frame_name {
  1840. background-color: rgb(%i, %i, %i);
  1841. border: 1px solid rgb(%i, %i, %i);
  1842. border-radius: 4px;
  1843. }
  1844. QFrame#frame_controls {
  1845. background-image: url(:/bitmaps/carla_knobs1.png);
  1846. background-color: rgb(35, 35, 35);
  1847. border: 1px solid rgb(35, 35, 35);
  1848. border-radius: 4px;
  1849. }
  1850. QFrame#frame_peaks {
  1851. background-color: rgb(35, 35, 35);
  1852. border: 1px solid rgb(35, 35, 35);
  1853. border-radius: 4px;
  1854. }
  1855. """ % (border_r, border_g, border_b,
  1856. border_r, border_g, border_b,
  1857. border_r, border_g, border_b,
  1858. border_r, border_g, border_b,
  1859. r, g, b,
  1860. border_r, border_g, border_b,
  1861. r, g, b, # frame_name background-color
  1862. border_r, border_g, border_b # frame_name border
  1863. ))
  1864. def recheck_hints(self, hints):
  1865. self.pinfo['hints'] = hints
  1866. self.dial_drywet.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_DRYWET)
  1867. self.dial_vol.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_VOLUME)
  1868. self.dial_b_left.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_BALANCE)
  1869. self.dial_b_right.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_BALANCE)
  1870. self.b_gui.setEnabled(self.pinfo['hints'] & PLUGIN_HAS_GUI)
  1871. def getSaveXMLContent(self):
  1872. CarlaHost.prepare_for_save(self.plugin_id)
  1873. if self.pinfo['type'] == PLUGIN_LADSPA:
  1874. type_str = "LADSPA"
  1875. elif self.pinfo['type'] == PLUGIN_DSSI:
  1876. type_str = "DSSI"
  1877. elif self.pinfo['type'] == PLUGIN_LV2:
  1878. type_str = "LV2"
  1879. elif self.pinfo['type'] == PLUGIN_VST:
  1880. type_str = "VST"
  1881. elif self.pinfo['type'] == PLUGIN_GIG:
  1882. type_str = "GIG"
  1883. elif self.pinfo['type'] == PLUGIN_SF2:
  1884. type_str = "SF2"
  1885. elif self.pinfo['type'] == PLUGIN_SFZ:
  1886. type_str = "SFZ"
  1887. else:
  1888. type_str = "Unknown"
  1889. x_save_state_dict = deepcopy(save_state_dict)
  1890. # ----------------------------
  1891. # Basic info
  1892. x_save_state_dict['Type'] = type_str
  1893. x_save_state_dict['Name'] = self.pinfo['name']
  1894. x_save_state_dict['Label'] = self.pinfo['label']
  1895. x_save_state_dict['Binary'] = self.pinfo['binary']
  1896. x_save_state_dict['UniqueID'] = self.pinfo['unique_id']
  1897. # ----------------------------
  1898. # Internals
  1899. x_save_state_dict['Active'] = self.led_enable.isChecked()
  1900. x_save_state_dict['DryWet'] = float(self.dial_drywet.value()) / 1000
  1901. x_save_state_dict['Volume'] = float(self.dial_vol.value()) / 1000
  1902. x_save_state_dict['Balance-Left'] = float(self.dial_b_left.value()) / 1000
  1903. x_save_state_dict['Balance-Right'] = float(self.dial_b_right.value()) / 1000
  1904. # ----------------------------
  1905. # Current Program
  1906. if (self.edit_dialog.cb_programs.currentIndex() >= 0):
  1907. x_save_state_dict['CurrentProgramIndex'] = self.edit_dialog.cb_programs.currentIndex()
  1908. x_save_state_dict['CurrentProgramName'] = self.edit_dialog.cb_programs.currentText()
  1909. # ----------------------------
  1910. # Current MIDI Program
  1911. if (self.edit_dialog.cb_midi_programs.currentIndex() >= 0):
  1912. midi_program_info = CarlaHost.get_midi_program_info(self.plugin_id, self.edit_dialog.cb_midi_programs.currentIndex())
  1913. x_save_state_dict['CurrentMidiBank'] = midi_program_info['bank']
  1914. x_save_state_dict['CurrentMidiProgram'] = midi_program_info['program']
  1915. # ----------------------------
  1916. # Parameters
  1917. parameter_count = CarlaHost.get_parameter_count(self.plugin_id)
  1918. for i in range(parameter_count):
  1919. parameter_info = CarlaHost.get_parameter_info(self.plugin_id, i)
  1920. parameter_data = CarlaHost.get_parameter_data(self.plugin_id, i)
  1921. if (not parameter_info['valid']) or parameter_data['type'] != PARAMETER_INPUT:
  1922. continue
  1923. x_save_state_parameter = deepcopy(save_state_parameter)
  1924. x_save_state_parameter['index'] = parameter_data['index']
  1925. x_save_state_parameter['name'] = cString(parameter_info['name'])
  1926. x_save_state_parameter['symbol'] = cString(parameter_info['symbol'])
  1927. x_save_state_parameter['value'] = CarlaHost.get_current_parameter_value(self.plugin_id, parameter_data['index'])
  1928. x_save_state_parameter['midi_channel'] = parameter_data['midi_channel'] + 1
  1929. x_save_state_parameter['midi_cc'] = parameter_data['midi_cc']
  1930. if (parameter_data['hints'] & PARAMETER_USES_SAMPLERATE):
  1931. x_save_state_parameter['value'] /= CarlaHost.get_sample_rate()
  1932. x_save_state_dict['Parameters'].append(x_save_state_parameter)
  1933. # ----------------------------
  1934. # Custom Data
  1935. custom_data_count = CarlaHost.get_custom_data_count(self.plugin_id)
  1936. for i in range(custom_data_count):
  1937. custom_data = CarlaHost.get_custom_data(self.plugin_id, i)
  1938. if custom_data['type'] == CUSTOM_DATA_INVALID:
  1939. continue
  1940. x_save_state_custom_data = deepcopy(save_state_custom_data)
  1941. x_save_state_custom_data['type'] = CustomDataType2String(custom_data['type'])
  1942. x_save_state_custom_data['key'] = cString(custom_data['key'])
  1943. x_save_state_custom_data['value'] = cString(custom_data['value'])
  1944. x_save_state_dict['CustomData'].append(x_save_state_custom_data)
  1945. # ----------------------------
  1946. # Chunk
  1947. if (self.pinfo['hints'] & PLUGIN_USES_CHUNKS):
  1948. x_save_state_dict['Chunk'] = cString(CarlaHost.get_chunk_data(self.plugin_id))
  1949. # ----------------------------
  1950. # Generate XML for this plugin
  1951. content = ""
  1952. content += " <Info>\n"
  1953. content += " <Type>%s</Type>\n" % x_save_state_dict['Type']
  1954. content += " <Name>%s</Name>\n" % xmlSafeString(x_save_state_dict['Name'], True)
  1955. if self.pinfo['type'] == PLUGIN_LV2:
  1956. content += " <URI>%s</URI>\n" % xmlSafeString(x_save_state_dict['Label'], True)
  1957. else:
  1958. if x_save_state_dict['Label']:
  1959. content += " <Label>%s</Label>\n" % xmlSafeString(x_save_state_dict['Label'], True)
  1960. content += " <Binary>%s</Binary>\n" % xmlSafeString(x_save_state_dict['Binary'], True)
  1961. if x_save_state_dict['UniqueID'] != 0:
  1962. content += " <UniqueID>%li</UniqueID>\n" % x_save_state_dict['UniqueID']
  1963. content += " </Info>\n"
  1964. content += "\n"
  1965. content += " <Data>\n"
  1966. content += " <Active>%s</Active>\n" % "Yes" if x_save_state_dict['Active'] else "No"
  1967. content += " <DryWet>%f</DryWet>\n" % x_save_state_dict['DryWet']
  1968. content += " <Volume>%f</Volume>\n" % x_save_state_dict['Volume']
  1969. content += " <Balance-Left>%f</Balance-Left>\n" % x_save_state_dict['Balance-Left']
  1970. content += " <Balance-Right>%f</Balance-Right>\n" % x_save_state_dict['Balance-Right']
  1971. for parameter in x_save_state_dict['Parameters']:
  1972. content += "\n"
  1973. content += " <Parameter>\n"
  1974. content += " <index>%i</index>\n" % parameter['index']
  1975. content += " <name>%s</name>\n" % xmlSafeString(parameter['name'], True)
  1976. if (parameter['symbol']):
  1977. content += " <symbol>%s</symbol>\n" % parameter['symbol']
  1978. content += " <value>%f</value>\n" % parameter['value']
  1979. if (parameter['midi_cc'] > 0):
  1980. content += " <midi_channel>%i</midi_channel>\n" % parameter['midi_channel']
  1981. content += " <midi_cc>%i</midi_cc>\n" % parameter['midi_cc']
  1982. content += " </Parameter>\n"
  1983. if (x_save_state_dict['CurrentProgramIndex'] >= 0):
  1984. content += "\n"
  1985. content += " <CurrentProgramIndex>%i</CurrentProgramIndex>\n" % x_save_state_dict['CurrentProgramIndex']
  1986. content += " <CurrentProgramName>%s</CurrentProgramName>\n" % xmlSafeString(x_save_state_dict['CurrentProgramName'], True)
  1987. if (x_save_state_dict['CurrentMidiBank'] >= 0 and x_save_state_dict['CurrentMidiProgram'] >= 0):
  1988. content += "\n"
  1989. content += " <CurrentMidiBank>%i</CurrentMidiBank>\n" % x_save_state_dict['CurrentMidiBank']
  1990. content += " <CurrentMidiProgram>%i</CurrentMidiProgram>\n" % x_save_state_dict['CurrentMidiProgram']
  1991. for custom_data in x_save_state_dict['CustomData']:
  1992. content += "\n"
  1993. content += " <CustomData>\n"
  1994. content += " <type>%s</type>\n" % custom_data['type']
  1995. content += " <key>%s</key>\n" % xmlSafeString(custom_data['key'], True)
  1996. if (custom_data['type'] in ("string", "chunk", "binary")):
  1997. content += " <value>\n"
  1998. content += "%s\n" % xmlSafeString(custom_data['value'], True)
  1999. content += " </value>\n"
  2000. else:
  2001. content += " <value>%s</value>\n" % xmlSafeString(custom_data['value'], True)
  2002. content += " </CustomData>\n"
  2003. if (x_save_state_dict['Chunk']):
  2004. content += "\n"
  2005. content += " <Chunk>\n"
  2006. content += "%s\n" % x_save_state_dict['Chunk']
  2007. content += " </Chunk>\n"
  2008. content += " </Data>\n"
  2009. return content
  2010. def loadStateDict(self, content):
  2011. # ---------------------------------------------------------------------
  2012. # Part 1 - set custom data
  2013. for custom_data in content['CustomData']:
  2014. CarlaHost.set_custom_data(self.plugin_id, custom_data['type'], custom_data['key'], custom_data['value'])
  2015. # ---------------------------------------------------------------------
  2016. # Part 2 - set program
  2017. program_id = -1
  2018. program_count = CarlaHost.get_program_count(self.plugin_id)
  2019. if (content['CurrentProgramName']):
  2020. test_pname = cString(CarlaHost.get_program_name(self.plugin_id, content['CurrentProgramIndex']))
  2021. # Program index and name matches
  2022. if (content['CurrentProgramName'] == test_pname):
  2023. program_id = content['CurrentProgramIndex']
  2024. # index < count
  2025. elif (content['CurrentProgramIndex'] < program_count):
  2026. program_id = content['CurrentProgramIndex']
  2027. # index not valid, try to find by name
  2028. else:
  2029. for i in range(program_count):
  2030. test_pname = cString(CarlaHost.get_program_name(self.plugin_id, i))
  2031. if (content['CurrentProgramName'] == test_pname):
  2032. program_id = i
  2033. break
  2034. # set program now, if valid
  2035. if (program_id >= 0):
  2036. CarlaHost.set_program(self.plugin_id, program_id)
  2037. self.edit_dialog.set_program(program_id)
  2038. # ---------------------------------------------------------------------
  2039. # Part 3 - set midi program
  2040. if (content['CurrentMidiBank'] >= 0 and content['CurrentMidiProgram'] >= 0):
  2041. midi_program_count = CarlaHost.get_midi_program_count(self.plugin_id)
  2042. for i in range(midi_program_count):
  2043. program_info = CarlaHost.get_midi_program_info(self.plugin_id, i)
  2044. if (program_info['bank'] == content['CurrentMidiBank'] and program_info['program'] == content[
  2045. 'CurrentMidiProgram']):
  2046. CarlaHost.set_midi_program(self.plugin_id, i)
  2047. self.edit_dialog.set_midi_program(i)
  2048. break
  2049. # ---------------------------------------------------------------------
  2050. # Part 4a - get plugin parameter symbols
  2051. param_symbols = [] # (index, symbol)
  2052. for parameter in content['Parameters']:
  2053. if (parameter['symbol']):
  2054. param_info = CarlaHost.get_parameter_info(self.plugin_id, parameter['index'])
  2055. if (param_info['valid'] and param_info['symbol']):
  2056. param_symbols.append((parameter['index'], cString(param_info['symbol'])))
  2057. # ---------------------------------------------------------------------
  2058. # Part 4b - set parameter values (carefully)
  2059. for parameter in content['Parameters']:
  2060. index = -1
  2061. if (content['Type'] == "LADSPA"):
  2062. # Try to set by symbol, otherwise use index
  2063. if (parameter['symbol']):
  2064. for param_symbol in param_symbols:
  2065. if (param_symbol[1] == parameter['symbol']):
  2066. index = param_symbol[0]
  2067. break
  2068. else:
  2069. index = parameter['index']
  2070. else:
  2071. index = parameter['index']
  2072. elif (content['Type'] == "LV2"):
  2073. # Symbol only
  2074. if (parameter['symbol']):
  2075. for param_symbol in param_symbols:
  2076. if (param_symbol[1] == parameter['symbol']):
  2077. index = param_symbol[0]
  2078. break
  2079. else:
  2080. print("Failed to find LV2 parameter symbol for %i -> %s" % (
  2081. parameter['index'], parameter['symbol']))
  2082. else:
  2083. print("LV2 Plugin parameter #%i, '%s', has no symbol" % (parameter['index'], parameter['name']))
  2084. else:
  2085. # Index only
  2086. index = parameter['index']
  2087. # Now set parameter
  2088. if (index >= 0):
  2089. param_data = CarlaHost.get_parameter_data(self.plugin_id, parameter['index'])
  2090. if (param_data['hints'] & PARAMETER_USES_SAMPLERATE):
  2091. parameter['value'] *= CarlaHost.get_sample_rate()
  2092. CarlaHost.set_parameter_value(self.plugin_id, index, parameter['value'])
  2093. CarlaHost.set_parameter_midi_channel(self.plugin_id, index, parameter['midi_channel'] - 1)
  2094. CarlaHost.set_parameter_midi_cc(self.plugin_id, index, parameter['midi_cc'])
  2095. else:
  2096. print("Could not set parameter data for %i -> %s" % (parameter['index'], parameter['name']))
  2097. # ---------------------------------------------------------------------
  2098. # Part 5 - set chunk data
  2099. if (content['Chunk']):
  2100. CarlaHost.set_chunk_data(self.plugin_id, content['Chunk'])
  2101. # ---------------------------------------------------------------------
  2102. # Part 6 - set internal stuff
  2103. self.set_drywet(content['DryWet'] * 1000, True, True)
  2104. self.set_volume(content['Volume'] * 1000, True, True)
  2105. self.set_balance_left(content['Balance-Left'] * 1000, True, True)
  2106. self.set_balance_right(content['Balance-Right'] * 1000, True, True)
  2107. self.edit_dialog.do_reload_all()
  2108. self.set_active(content['Active'], True, True)
  2109. def check_gui_stuff(self):
  2110. # Input peaks
  2111. if (self.peaks_in > 0):
  2112. if (self.peaks_in > 1):
  2113. peak1 = CarlaHost.get_input_peak_value(self.plugin_id, 1)
  2114. peak2 = CarlaHost.get_input_peak_value(self.plugin_id, 2)
  2115. led_ain_state = bool(peak1 != 0.0 or peak2 != 0.0)
  2116. self.peak_in.displayMeter(1, peak1)
  2117. self.peak_in.displayMeter(2, peak2)
  2118. else:
  2119. peak = CarlaHost.get_input_peak_value(self.plugin_id, 1)
  2120. led_ain_state = bool(peak != 0.0)
  2121. self.peak_in.displayMeter(1, peak)
  2122. if (led_ain_state != self.last_led_ain_state):
  2123. self.led_audio_in.setChecked(led_ain_state)
  2124. self.last_led_ain_state = led_ain_state
  2125. # Output peaks
  2126. if (self.peaks_out > 0):
  2127. if (self.peaks_out > 1):
  2128. peak1 = CarlaHost.get_output_peak_value(self.plugin_id, 1)
  2129. peak2 = CarlaHost.get_output_peak_value(self.plugin_id, 2)
  2130. led_aout_state = bool(peak1 != 0.0 or peak2 != 0.0)
  2131. self.peak_out.displayMeter(1, peak1)
  2132. self.peak_out.displayMeter(2, peak2)
  2133. else:
  2134. peak = CarlaHost.get_output_peak_value(self.plugin_id, 1)
  2135. led_aout_state = bool(peak != 0.0)
  2136. self.peak_out.displayMeter(1, peak)
  2137. if (led_aout_state != self.last_led_aout_state):
  2138. self.led_audio_out.setChecked(led_aout_state)
  2139. self.last_led_aout_state = led_aout_state
  2140. def check_gui_stuff2(self):
  2141. # Parameter Activity LED
  2142. if (self.parameter_activity_timer == ICON_STATE_ON):
  2143. self.led_control.setChecked(True)
  2144. self.parameter_activity_timer = ICON_STATE_WAIT
  2145. elif (self.parameter_activity_timer == ICON_STATE_WAIT):
  2146. self.parameter_activity_timer = ICON_STATE_OFF
  2147. elif (self.parameter_activity_timer == ICON_STATE_OFF):
  2148. self.led_control.setChecked(False)
  2149. self.parameter_activity_timer = None
  2150. # Update edit dialog
  2151. self.edit_dialog.check_gui_stuff()
  2152. @pyqtSlot(bool)
  2153. def slot_setActive(self, yesno):
  2154. self.set_active(yesno, False, True)
  2155. @pyqtSlot(int)
  2156. def slot_setDryWet(self, value):
  2157. self.set_drywet(value, False, True)
  2158. @pyqtSlot(int)
  2159. def slot_setVolume(self, value):
  2160. self.set_volume(value, False, True)
  2161. @pyqtSlot(int)
  2162. def slot_setBalanceLeft(self, value):
  2163. self.set_balance_left(value, False, True)
  2164. @pyqtSlot(int)
  2165. def slot_setBalanceRight(self, value):
  2166. self.set_balance_right(value, False, True)
  2167. @pyqtSlot(bool)
  2168. def slot_guiClicked(self, show):
  2169. if (self.gui_dialog_type in (GUI_INTERNAL_QT4, GUI_INTERNAL_X11)):
  2170. if (show):
  2171. if (self.gui_dialog_geometry):
  2172. self.gui_dialog.restoreGeometry(self.gui_dialog_geometry)
  2173. else:
  2174. self.gui_dialog_geometry = self.gui_dialog.saveGeometry()
  2175. self.gui_dialog.setVisible(show)
  2176. CarlaHost.show_gui(self.plugin_id, show)
  2177. @pyqtSlot()
  2178. def slot_guiClosed(self):
  2179. self.b_gui.setChecked(False)
  2180. @pyqtSlot(bool)
  2181. def slot_editClicked(self, show):
  2182. if (show):
  2183. if (self.edit_dialog_geometry):
  2184. self.edit_dialog.restoreGeometry(self.edit_dialog_geometry)
  2185. else:
  2186. self.edit_dialog_geometry = self.edit_dialog.saveGeometry()
  2187. self.edit_dialog.setVisible(show)
  2188. @pyqtSlot()
  2189. def slot_editClosed(self):
  2190. self.b_edit.setChecked(False)
  2191. @pyqtSlot()
  2192. def slot_removeClicked(self):
  2193. gui.remove_plugin(self.plugin_id, True)
  2194. @pyqtSlot()
  2195. def slot_showCustomDialMenu(self):
  2196. dial_name = self.sender().objectName()
  2197. if (dial_name == "dial_drywet"):
  2198. minimum = 0
  2199. maximum = 100
  2200. default = 100
  2201. label = "Dry/Wet"
  2202. elif (dial_name == "dial_vol"):
  2203. minimum = 0
  2204. maximum = 127
  2205. default = 100
  2206. label = "Volume"
  2207. elif (dial_name == "dial_b_left"):
  2208. minimum = -100
  2209. maximum = 100
  2210. default = -100
  2211. label = "Balance-Left"
  2212. elif (dial_name == "dial_b_right"):
  2213. minimum = -100
  2214. maximum = 100
  2215. default = 100
  2216. label = "Balance-Right"
  2217. else:
  2218. minimum = 0
  2219. maximum = 100
  2220. default = 100
  2221. label = "Unknown"
  2222. current = self.sender().value() / 10
  2223. menu = QMenu(self)
  2224. act_x_reset = menu.addAction(self.tr("Reset (%i%%)" % (default)))
  2225. menu.addSeparator()
  2226. act_x_min = menu.addAction(self.tr("Set to Minimum (%i%%)" % (minimum)))
  2227. act_x_cen = menu.addAction(self.tr("Set to Center"))
  2228. act_x_max = menu.addAction(self.tr("Set to Maximum (%i%%)" % (maximum)))
  2229. menu.addSeparator()
  2230. act_x_set = menu.addAction(self.tr("Set value..."))
  2231. if (label not in ("Balance-Left", "Balance-Right")):
  2232. menu.removeAction(act_x_cen)
  2233. act_x_sel = menu.exec_(QCursor.pos())
  2234. if (act_x_sel == act_x_set):
  2235. value_try = QInputDialog.getInteger(self, self.tr("Set value"), label, current, minimum, maximum, 1)
  2236. if (value_try[1]):
  2237. value = value_try[0] * 10
  2238. else:
  2239. value = None
  2240. elif (act_x_sel == act_x_min):
  2241. value = minimum * 10
  2242. elif (act_x_sel == act_x_max):
  2243. value = maximum * 10
  2244. elif (act_x_sel == act_x_reset):
  2245. value = default * 10
  2246. elif (act_x_sel == act_x_cen):
  2247. value = 0
  2248. else:
  2249. value = None
  2250. if (value != None):
  2251. if (label == "Dry/Wet"):
  2252. self.set_drywet(value, True, True)
  2253. elif (label == "Volume"):
  2254. self.set_volume(value, True, True)
  2255. elif (label == "Balance-Left"):
  2256. self.set_balance_left(value, True, True)
  2257. elif (label == "Balance-Right"):
  2258. self.set_balance_right(value, True, True)
  2259. def paintEvent(self, event):
  2260. painter = QPainter(self)
  2261. painter.setPen(self.color_1)
  2262. painter.drawLine(0, 3, self.width(), 3)
  2263. painter.drawLine(0, self.height() - 4, self.width(), self.height() - 4)
  2264. painter.setPen(self.color_2)
  2265. painter.drawLine(0, 2, self.width(), 2)
  2266. painter.drawLine(0, self.height() - 3, self.width(), self.height() - 3)
  2267. painter.setPen(self.color_3)
  2268. painter.drawLine(0, 1, self.width(), 1)
  2269. painter.drawLine(0, self.height() - 2, self.width(), self.height() - 2)
  2270. painter.setPen(self.color_4)
  2271. painter.drawLine(0, 0, self.width(), 0)
  2272. painter.drawLine(0, self.height() - 1, self.width(), self.height() - 1)
  2273. QFrame.paintEvent(self, event)
  2274. # Main Window
  2275. class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW):
  2276. def __init__(self, parent=None):
  2277. QMainWindow.__init__(self, parent)
  2278. self.setupUi(self)
  2279. # -------------------------------------------------------------
  2280. # Load Settings
  2281. self.settings = QSettings("Cadence", "Carla")
  2282. self.settings_db = QSettings("Cadence", "Carla-Database")
  2283. self.loadSettings(True)
  2284. self.loadRDFs()
  2285. self.setStyleSheet("""
  2286. QWidget#centralwidget {
  2287. background-color: qlineargradient(spread:pad,
  2288. x1:0.0, y1:0.0,
  2289. x2:0.2, y2:1.0,
  2290. stop:0 rgb( 7, 7, 7),
  2291. stop:1 rgb(28, 28, 28)
  2292. );
  2293. }
  2294. """)
  2295. # -------------------------------------------------------------
  2296. # Internal stuff
  2297. self.m_bridge_info = None
  2298. self.m_project_filename = None
  2299. self.m_plugin_list = []
  2300. for x in range(MAX_PLUGINS):
  2301. self.m_plugin_list.append(None)
  2302. CarlaHost.set_callback_function(self.callback_function)
  2303. # -------------------------------------------------------------
  2304. # Set-up GUI stuff
  2305. self.act_plugin_remove_all.setEnabled(False)
  2306. self.resize(self.width(), 0)
  2307. # -------------------------------------------------------------
  2308. # Connect actions to functions
  2309. self.connect(self.act_file_new, SIGNAL("triggered()"), SLOT("slot_file_new()"))
  2310. self.connect(self.act_file_open, SIGNAL("triggered()"), SLOT("slot_file_open()"))
  2311. self.connect(self.act_file_save, SIGNAL("triggered()"), SLOT("slot_file_save()"))
  2312. self.connect(self.act_file_save_as, SIGNAL("triggered()"), SLOT("slot_file_save_as()"))
  2313. self.connect(self.act_plugin_add, SIGNAL("triggered()"), SLOT("slot_plugin_add()"))
  2314. self.connect(self.act_plugin_remove_all, SIGNAL("triggered()"), SLOT("slot_remove_all()"))
  2315. self.connect(self.act_settings_configure, SIGNAL("triggered()"), SLOT("slot_configureCarla()"))
  2316. self.connect(self.act_help_about, SIGNAL("triggered()"), SLOT("slot_aboutCarla()"))
  2317. self.connect(self.act_help_about_qt, SIGNAL("triggered()"), app, SLOT("aboutQt()"))
  2318. self.connect(self, SIGNAL("SIGUSR1()"), SLOT("slot_handleSIGUSR1()"))
  2319. self.connect(self, SIGNAL("DebugCallback(int, int, int, double)"), SLOT("slot_handleDebugCallback(int, int, int, double)"))
  2320. self.connect(self, SIGNAL("ParameterCallback(int, int, double)"), SLOT("slot_handleParameterCallback(int, int, double)"))
  2321. self.connect(self, SIGNAL("ProgramCallback(int, int)"), SLOT("slot_handleProgramCallback(int, int)"))
  2322. self.connect(self, SIGNAL("MidiProgramCallback(int, int)"), SLOT("slot_handleMidiProgramCallback(int, int)"))
  2323. self.connect(self, SIGNAL("NoteOnCallback(int, int, int)"), SLOT("slot_handleNoteOnCallback(int, int)"))
  2324. self.connect(self, SIGNAL("NoteOffCallback(int, int)"), SLOT("slot_handleNoteOffCallback(int, int)"))
  2325. self.connect(self, SIGNAL("ShowGuiCallback(int, int)"), SLOT("slot_handleShowGuiCallback(int, int)"))
  2326. self.connect(self, SIGNAL("ResizeGuiCallback(int, int, int)"), SLOT("slot_handleResizeGuiCallback(int, int, int)"))
  2327. self.connect(self, SIGNAL("UpdateCallback(int)"), SLOT("slot_handleUpdateCallback(int)"))
  2328. self.connect(self, SIGNAL("ReloadInfoCallback(int)"), SLOT("slot_handleReloadInfoCallback(int)"))
  2329. self.connect(self, SIGNAL("ReloadParametersCallback(int)"), SLOT("slot_handleReloadParametersCallback(int)"))
  2330. self.connect(self, SIGNAL("ReloadProgramsCallback(int)"), SLOT("slot_handleReloadProgramsCallback(int)"))
  2331. self.connect(self, SIGNAL("ReloadAllCallback(int)"), SLOT("slot_handleReloadAllCallback(int)"))
  2332. self.connect(self, SIGNAL("QuitCallback()"), SLOT("slot_handleQuitCallback()"))
  2333. self.TIMER_GUI_STUFF = self.startTimer(self.m_savedSettings["Main/RefreshInterval"]) # Peaks
  2334. self.TIMER_GUI_STUFF2 = self.startTimer(self.m_savedSettings["Main/RefreshInterval"] * 2) # LEDs and edit dialog
  2335. def callback_function(self, action, plugin_id, value1, value2, value3):
  2336. if (plugin_id < 0 or plugin_id >= MAX_PLUGINS):
  2337. return
  2338. if (action == CALLBACK_DEBUG):
  2339. self.emit(SIGNAL("DebugCallback(int, int, int, double)"), plugin_id, value1, value2, value3)
  2340. elif (action == CALLBACK_PARAMETER_CHANGED):
  2341. self.emit(SIGNAL("ParameterCallback(int, int, double)"), plugin_id, value1, value3)
  2342. elif (action == CALLBACK_PROGRAM_CHANGED):
  2343. self.emit(SIGNAL("ProgramCallback(int, int)"), plugin_id, value1)
  2344. elif (action == CALLBACK_MIDI_PROGRAM_CHANGED):
  2345. self.emit(SIGNAL("MidiProgramCallback(int, int)"), plugin_id, value1)
  2346. elif (action == CALLBACK_NOTE_ON):
  2347. self.emit(SIGNAL("NoteOnCallback(int, int, int)"), plugin_id, value1, value2)
  2348. elif (action == CALLBACK_NOTE_OFF):
  2349. self.emit(SIGNAL("NoteOffCallback(int, int)"), plugin_id, value1)
  2350. elif (action == CALLBACK_SHOW_GUI):
  2351. self.emit(SIGNAL("ShowGuiCallback(int, int)"), plugin_id, value1)
  2352. elif (action == CALLBACK_RESIZE_GUI):
  2353. self.emit(SIGNAL("ResizeGuiCallback(int, int, int)"), plugin_id, value1, value2)
  2354. elif (action == CALLBACK_UPDATE):
  2355. self.emit(SIGNAL("UpdateCallback(int)"), plugin_id)
  2356. elif (action == CALLBACK_RELOAD_INFO):
  2357. self.emit(SIGNAL("ReloadInfoCallback(int)"), plugin_id)
  2358. elif (action == CALLBACK_RELOAD_PARAMETERS):
  2359. self.emit(SIGNAL("ReloadParametersCallback(int)"), plugin_id)
  2360. elif (action == CALLBACK_RELOAD_PROGRAMS):
  2361. self.emit(SIGNAL("ReloadProgramsCallback(int)"), plugin_id)
  2362. elif (action == CALLBACK_RELOAD_ALL):
  2363. self.emit(SIGNAL("ReloadAllCallback(int)"), plugin_id)
  2364. elif (action == CALLBACK_QUIT):
  2365. self.emit(SIGNAL("QuitCallback()"))
  2366. @pyqtSlot()
  2367. def slot_handleSIGUSR1(self):
  2368. print("Got SIGUSR1 -> Saving project now")
  2369. QTimer.singleShot(0, self, SLOT("slot_file_save()"))
  2370. @pyqtSlot(int, int, int, float)
  2371. def slot_handleDebugCallback(self, plugin_id, value1, value2, value3):
  2372. print("DEBUG :: %i, %i, %i, %f)" % (plugin_id, value1, value2, value3))
  2373. @pyqtSlot(int, int, float)
  2374. def slot_handleParameterCallback(self, plugin_id, parameter_id, value):
  2375. pwidget = self.m_plugin_list[plugin_id]
  2376. if (pwidget):
  2377. pwidget.parameter_activity_timer = ICON_STATE_ON
  2378. if (parameter_id == PARAMETER_ACTIVE):
  2379. pwidget.set_active((value > 0.0), True, False)
  2380. elif (parameter_id == PARAMETER_DRYWET):
  2381. pwidget.set_drywet(value * 1000, True, False)
  2382. elif (parameter_id == PARAMETER_VOLUME):
  2383. pwidget.set_volume(value * 1000, True, False)
  2384. elif (parameter_id == PARAMETER_BALANCE_LEFT):
  2385. pwidget.set_balance_left(value * 1000, True, False)
  2386. elif (parameter_id == PARAMETER_BALANCE_RIGHT):
  2387. pwidget.set_balance_right(value * 1000, True, False)
  2388. elif (parameter_id >= 0):
  2389. pwidget.edit_dialog.set_parameter_to_update(parameter_id)
  2390. @pyqtSlot(int, int)
  2391. def slot_handleProgramCallback(self, plugin_id, program_id):
  2392. pwidget = self.m_plugin_list[plugin_id]
  2393. if (pwidget):
  2394. pwidget.edit_dialog.set_program(program_id)
  2395. @pyqtSlot(int, int)
  2396. def slot_handleMidiProgramCallback(self, plugin_id, midi_program_id):
  2397. pwidget = self.m_plugin_list[plugin_id]
  2398. if (pwidget):
  2399. pwidget.edit_dialog.set_midi_program(midi_program_id)
  2400. @pyqtSlot(int, int)
  2401. def slot_handleNoteOnCallback(self, plugin_id, note):
  2402. pwidget = self.m_plugin_list[plugin_id]
  2403. if (pwidget):
  2404. pwidget.edit_dialog.keyboard.sendNoteOn(note, False)
  2405. @pyqtSlot(int, int)
  2406. def slot_handleNoteOffCallback(self, plugin_id, note):
  2407. pwidget = self.m_plugin_list[plugin_id]
  2408. if (pwidget):
  2409. pwidget.edit_dialog.keyboard.sendNoteOff(note, False)
  2410. @pyqtSlot(int, int)
  2411. def slot_handleShowGuiCallback(self, plugin_id, show):
  2412. pwidget = self.m_plugin_list[plugin_id]
  2413. if (pwidget):
  2414. if (show == 0):
  2415. pwidget.b_gui.setChecked(False)
  2416. pwidget.b_gui.setEnabled(True)
  2417. elif (show == 1):
  2418. pwidget.b_gui.setChecked(True)
  2419. pwidget.b_gui.setEnabled(True)
  2420. elif (show == -1):
  2421. pwidget.b_gui.setChecked(False)
  2422. pwidget.b_gui.setEnabled(False)
  2423. @pyqtSlot(int, int, int)
  2424. def slot_handleResizeGuiCallback(self, plugin_id, width, height):
  2425. pwidget = self.m_plugin_list[plugin_id]
  2426. if (pwidget):
  2427. gui_dialog = pwidget.gui_dialog
  2428. if (gui_dialog):
  2429. gui_dialog.setNewSize(width, height)
  2430. @pyqtSlot(int)
  2431. def slot_handleUpdateCallback(self, plugin_id):
  2432. pwidget = self.m_plugin_list[plugin_id]
  2433. if (pwidget):
  2434. pwidget.edit_dialog.do_update()
  2435. @pyqtSlot(int)
  2436. def slot_handleReloadInfoCallback(self, plugin_id):
  2437. pwidget = self.m_plugin_list[plugin_id]
  2438. if (pwidget):
  2439. pwidget.edit_dialog.do_reload_info()
  2440. @pyqtSlot(int)
  2441. def slot_handleReloadParametersCallback(self, plugin_id):
  2442. pwidget = self.m_plugin_list[plugin_id]
  2443. if (pwidget):
  2444. pwidget.edit_dialog.do_reload_parameters()
  2445. @pyqtSlot(int)
  2446. def slot_handleReloadProgramsCallback(self, plugin_id):
  2447. pwidget = self.m_plugin_list[plugin_id]
  2448. if (pwidget):
  2449. pwidget.edit_dialog.do_reload_programs()
  2450. @pyqtSlot(int)
  2451. def slot_handleReloadAllCallback(self, plugin_id):
  2452. pwidget = self.m_plugin_list[plugin_id]
  2453. if (pwidget):
  2454. pwidget.edit_dialog.do_reload_all()
  2455. @pyqtSlot()
  2456. def slot_handleQuitCallback(self):
  2457. CustomMessageBox(self, QMessageBox.Warning, self.tr("Warning"),
  2458. self.tr("JACK has been stopped or crashed.\nPlease start JACK and restart Carla"),
  2459. "You may want to save your session now...", QMessageBox.Ok, QMessageBox.Ok)
  2460. def add_plugin(self, btype, ptype, filename, label, extra_stuff, activate):
  2461. new_plugin_id = CarlaHost.add_plugin(btype, ptype, filename, label, extra_stuff)
  2462. if (new_plugin_id < 0):
  2463. CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to load plugin"),
  2464. cString(CarlaHost.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)
  2465. else:
  2466. pwidget = PluginWidget(self, new_plugin_id)
  2467. self.w_plugins.layout().addWidget(pwidget)
  2468. self.m_plugin_list[new_plugin_id] = pwidget
  2469. self.act_plugin_remove_all.setEnabled(True)
  2470. pwidget.peak_in.setRefreshRate(self.m_savedSettings["Main/RefreshInterval"])
  2471. pwidget.peak_out.setRefreshRate(self.m_savedSettings["Main/RefreshInterval"])
  2472. if (activate):
  2473. pwidget.set_active(True, True, True)
  2474. return new_plugin_id
  2475. def remove_plugin(self, plugin_id, showError):
  2476. pwidget = self.m_plugin_list[plugin_id]
  2477. pwidget.edit_dialog.close()
  2478. if (pwidget.gui_dialog):
  2479. pwidget.gui_dialog.close()
  2480. if (CarlaHost.remove_plugin(plugin_id)):
  2481. pwidget.close()
  2482. pwidget.deleteLater()
  2483. self.w_plugins.layout().removeWidget(pwidget)
  2484. self.m_plugin_list[plugin_id] = None
  2485. else:
  2486. if (showError):
  2487. CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to remove plugin"),
  2488. cString(CarlaHost.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)
  2489. for i in range(MAX_PLUGINS):
  2490. if (self.m_plugin_list[i] != None):
  2491. self.act_plugin_remove_all.setEnabled(True)
  2492. break
  2493. else:
  2494. self.act_plugin_remove_all.setEnabled(False)
  2495. def get_extra_stuff(self, plugin):
  2496. build = plugin['build']
  2497. ptype = plugin['type']
  2498. if (build != BINARY_NATIVE):
  2499. # Store object so we can return a pointer
  2500. if self.m_bridge_info is None:
  2501. self.m_bridge_info = PluginBridgeInfo()
  2502. self.m_bridge_info.hints = plugin['hints']
  2503. self.m_bridge_info.name = plugin['name'].encode("utf-8")
  2504. self.m_bridge_info.maker = plugin['maker'].encode("utf-8")
  2505. self.m_bridge_info.unique_id = plugin['unique_id']
  2506. self.m_bridge_info.ains = plugin['audio.ins']
  2507. self.m_bridge_info.aouts = plugin['audio.outs']
  2508. self.m_bridge_info.mins = plugin['midi.ins']
  2509. self.m_bridge_info.mouts = plugin['midi.outs']
  2510. return pointer(self.m_bridge_info)
  2511. elif (ptype == PLUGIN_LADSPA):
  2512. unique_id = plugin['unique_id']
  2513. for rdf_item in self.ladspa_rdf_list:
  2514. if (rdf_item.UniqueID == unique_id):
  2515. return pointer(rdf_item)
  2516. else:
  2517. return c_nullptr
  2518. elif (ptype == PLUGIN_DSSI):
  2519. if (plugin['hints'] & PLUGIN_HAS_GUI):
  2520. gui = findDSSIGUI(plugin['binary'], plugin['name'], plugin['label'])
  2521. if (gui):
  2522. return gui.encode("utf-8")
  2523. return c_nullptr
  2524. else:
  2525. return c_nullptr
  2526. def save_project(self):
  2527. content = ("<?xml version='1.0' encoding='UTF-8'?>\n"
  2528. "<!DOCTYPE CARLA-PROJECT>\n"
  2529. "<CARLA-PROJECT VERSION='%s'>\n") % (VERSION)
  2530. first_plugin = True
  2531. for pwidget in self.m_plugin_list:
  2532. if pwidget:
  2533. if not first_plugin:
  2534. content += "\n"
  2535. real_plugin_name = cString(CarlaHost.get_real_plugin_name(pwidget.plugin_id))
  2536. if real_plugin_name:
  2537. content += " <!-- %s -->\n" % xmlSafeString(real_plugin_name, True)
  2538. content += " <Plugin>\n"
  2539. content += pwidget.getSaveXMLContent()
  2540. content += " </Plugin>\n"
  2541. first_plugin = False
  2542. content += "</CARLA-PROJECT>\n"
  2543. try:
  2544. open(self.m_project_filename, "w").write(content)
  2545. except:
  2546. QMessageBox.critical(self, self.tr("Error"), self.tr("Failed to save project file"))
  2547. def load_project(self):
  2548. try:
  2549. project_read = open(self.m_project_filename, "r").read()
  2550. except:
  2551. project_read = None
  2552. if not project_read:
  2553. QMessageBox.critical(self, self.tr("Error"), self.tr("Failed to load project file"))
  2554. return
  2555. xml = QDomDocument()
  2556. xml.setContent(project_read)
  2557. xml_node = xml.documentElement()
  2558. if xml_node.tagName() != "CARLA-PROJECT":
  2559. QMessageBox.critical(self, self.tr("Error"), self.tr("Not a valid Carla project file"))
  2560. return
  2561. x_ladspa_plugins = None
  2562. x_dssi_plugins = None
  2563. x_lv2_plugins = None
  2564. x_vst_plugins = None
  2565. x_gig_plugins = None
  2566. x_sf2_plugins = None
  2567. x_sfz_plugins = None
  2568. x_failed_plugins = []
  2569. x_save_state_dicts = []
  2570. node = xml_node.firstChild()
  2571. while not node.isNull():
  2572. if node.toElement().tagName() == "Plugin":
  2573. x_save_state_dict = getStateDictFromXML(node)
  2574. x_save_state_dicts.append(x_save_state_dict)
  2575. node = node.nextSibling()
  2576. for x_save_state_dict in x_save_state_dicts:
  2577. ptype = x_save_state_dict['Type']
  2578. label = x_save_state_dict['Label']
  2579. binary = x_save_state_dict['Binary']
  2580. binaryS = os.path.basename(binary)
  2581. unique_id = x_save_state_dict['UniqueID']
  2582. if ptype == "LADSPA":
  2583. if not x_ladspa_plugins:
  2584. x_ladspa_plugins = []
  2585. x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_unix32", []))
  2586. x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_unix64", []))
  2587. x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_win32", []))
  2588. x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_win64", []))
  2589. x_plugins = x_ladspa_plugins
  2590. elif ptype == "DSSI":
  2591. if not x_dssi_plugins:
  2592. x_dssi_plugins = []
  2593. x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_unix32", []))
  2594. x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_unix64", []))
  2595. x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_win32", []))
  2596. x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_win64", []))
  2597. x_plugins = x_dssi_plugins
  2598. elif ptype == "LV2":
  2599. if not x_lv2_plugins:
  2600. x_lv2_plugins = []
  2601. x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_unix32", []))
  2602. x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_unix64", []))
  2603. x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_win32", []))
  2604. x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_win64", []))
  2605. x_plugins = x_lv2_plugins
  2606. elif ptype == "VST":
  2607. if not x_vst_plugins:
  2608. x_vst_plugins = []
  2609. x_vst_plugins += toList(self.settings_db.value("Plugins/VST_unix32", []))
  2610. x_vst_plugins += toList(self.settings_db.value("Plugins/VST_unix64", []))
  2611. x_vst_plugins += toList(self.settings_db.value("Plugins/VST_win32", []))
  2612. x_vst_plugins += toList(self.settings_db.value("Plugins/VST_win64", []))
  2613. x_plugins = x_vst_plugins
  2614. elif ptype == "GIG":
  2615. if not x_gig_plugins: x_gig_plugins = toList(self.settings_db.value("Plugins/GIG", []))
  2616. x_plugins = x_gig_plugins
  2617. elif ptype == "SF2":
  2618. if not x_sf2_plugins: x_sf2_plugins = toList(self.settings_db.value("Plugins/SF2", []))
  2619. x_plugins = x_sf2_plugins
  2620. elif ptype == "SFZ":
  2621. if not x_sfz_plugins: x_sfz_plugins = toList(self.settings_db.value("Plugins/SFZ", []))
  2622. x_plugins = x_sfz_plugins
  2623. else:
  2624. print("load_project() - ptype '%s' not recognized", ptype)
  2625. x_failed_plugins.append(x_save_state_dict['Name'])
  2626. continue
  2627. # Try UniqueID -> Label -> Binary (full) -> Binary (short)
  2628. plugin_ulB = None
  2629. plugin_ulb = None
  2630. plugin_ul = None
  2631. plugin_uB = None
  2632. plugin_ub = None
  2633. plugin_lB = None
  2634. plugin_lb = None
  2635. plugin_u = None
  2636. plugin_l = None
  2637. plugin_B = None
  2638. for _plugins in x_plugins:
  2639. for x_plugin in _plugins:
  2640. if unique_id == x_plugin['unique_id'] and label == x_plugin['label'] and binary == x_plugin['binary']:
  2641. plugin_ulB = x_plugin
  2642. break
  2643. elif unique_id == x_plugin['unique_id'] and label == x_plugin['label'] and binaryS == os.path.basename(x_plugin['binary']):
  2644. plugin_ulb = x_plugin
  2645. elif unique_id == x_plugin['unique_id'] and label == x_plugin['label']:
  2646. plugin_ul = x_plugin
  2647. elif unique_id == x_plugin['unique_id'] and binary == x_plugin['binary']:
  2648. plugin_uB = x_plugin
  2649. elif unique_id == x_plugin['unique_id'] and binaryS == os.path.basename(x_plugin['binary']):
  2650. plugin_ub = x_plugin
  2651. elif label == x_plugin['label'] and binary == x_plugin['binary']:
  2652. plugin_lB = x_plugin
  2653. elif label == x_plugin['label'] and binaryS == os.path.basename(x_plugin['binary']):
  2654. plugin_lb = x_plugin
  2655. elif unique_id == x_plugin['unique_id']:
  2656. plugin_u = x_plugin
  2657. elif label == x_plugin['label']:
  2658. plugin_l = x_plugin
  2659. elif binary == x_plugin['binary']:
  2660. plugin_B = x_plugin
  2661. # LADSPA uses UniqueID or binary+label
  2662. if ptype == "LADSPA":
  2663. plugin_l = None
  2664. plugin_B = None
  2665. # DSSI uses binary+label (UniqueID ignored)
  2666. elif ptype == "DSSI":
  2667. plugin_ul = None
  2668. plugin_uB = None
  2669. plugin_ub = None
  2670. plugin_u = None
  2671. plugin_l = None
  2672. plugin_B = None
  2673. # LV2 uses URIs (label in this case)
  2674. elif ptype == "LV2":
  2675. plugin_uB = None
  2676. plugin_ub = None
  2677. plugin_u = None
  2678. plugin_B = None
  2679. # VST uses UniqueID
  2680. elif ptype == "VST":
  2681. plugin_lB = None
  2682. plugin_lb = None
  2683. plugin_l = None
  2684. plugin_B = None
  2685. # Sound Kits use binaries
  2686. elif ptype in ("GIG", "SF2", "SFZ"):
  2687. plugin_ul = None
  2688. plugin_u = None
  2689. plugin_l = None
  2690. if (plugin_ulB):
  2691. plugin = plugin_ulB
  2692. elif (plugin_ulb):
  2693. plugin = plugin_ulb
  2694. elif (plugin_ul):
  2695. plugin = plugin_ul
  2696. elif (plugin_uB):
  2697. plugin = plugin_uB
  2698. elif (plugin_ub):
  2699. plugin = plugin_ub
  2700. elif (plugin_lB):
  2701. plugin = plugin_lB
  2702. elif (plugin_lb):
  2703. plugin = plugin_lb
  2704. elif (plugin_u):
  2705. plugin = plugin_u
  2706. elif (plugin_l):
  2707. plugin = plugin_l
  2708. elif (plugin_B):
  2709. plugin = plugin_B
  2710. else:
  2711. plugin = None
  2712. print(plugin, ptype, len(x_plugins), plugin_l)
  2713. if plugin:
  2714. btype = plugin['build']
  2715. ptype = plugin['type']
  2716. filename = plugin['binary']
  2717. label = plugin['label']
  2718. extra_stuff = self.get_extra_stuff(plugin)
  2719. new_plugin_id = self.add_plugin(btype, ptype, filename, label, extra_stuff, False)
  2720. if new_plugin_id >= 0:
  2721. pwidget = self.m_plugin_list[new_plugin_id]
  2722. pwidget.loadStateDict(x_save_state_dict)
  2723. else:
  2724. x_failed_plugins.append(x_save_state_dict['Name'])
  2725. else:
  2726. x_failed_plugins.append(x_save_state_dict['Name'])
  2727. if len(x_failed_plugins) > 0:
  2728. text = self.tr("The following plugins were not found or failed to initialize:\n")
  2729. for plugin in x_failed_plugins:
  2730. text += " - %s\n" % plugin
  2731. self.statusBar().showMessage("State file loaded with errors")
  2732. QMessageBox.critical(self, self.tr("Error"), text)
  2733. else:
  2734. self.statusBar().showMessage("State file loaded sucessfully!")
  2735. def loadRDFs(self):
  2736. # Save RDF info for later
  2737. if haveLRDF:
  2738. SettingsDir = os.path.join(HOME, ".config", "Cadence")
  2739. fr_ladspa_file = os.path.join(SettingsDir, "ladspa_rdf.db")
  2740. if os.path.exists(fr_ladspa_file):
  2741. fr_ladspa = open(fr_ladspa_file, 'r')
  2742. if fr_ladspa:
  2743. try:
  2744. self.ladspa_rdf_list = ladspa_rdf.get_c_ladspa_rdfs(json.load(fr_ladspa))
  2745. except:
  2746. self.ladspa_rdf_list = []
  2747. fr_ladspa.close()
  2748. return
  2749. self.ladspa_rdf_list = []
  2750. @pyqtSlot()
  2751. def slot_file_new(self):
  2752. self.slot_remove_all()
  2753. self.m_project_filename = None
  2754. self.setWindowTitle("Carla")
  2755. @pyqtSlot()
  2756. def slot_file_open(self):
  2757. file_filter = self.tr("Carla Project File (*.carxp)")
  2758. filename = QFileDialog.getOpenFileName(self, self.tr("Open Carla Project File"),
  2759. self.m_savedSettings["Main/DefaultProjectFolder"], filter=file_filter)
  2760. if filename:
  2761. self.m_project_filename = filename
  2762. self.slot_remove_all()
  2763. self.load_project()
  2764. self.setWindowTitle("Carla - %s" % os.path.basename(self.m_project_filename))
  2765. @pyqtSlot()
  2766. def slot_file_save(self, saveAs=False):
  2767. if self.m_project_filename == None or saveAs:
  2768. file_filter = self.tr("Carla Project File (*.carxp)")
  2769. filename = QFileDialog.getSaveFileName(self, self.tr("Save Carla Project File"),
  2770. self.m_savedSettings["Main/DefaultProjectFolder"], filter=file_filter)
  2771. if filename:
  2772. self.m_project_filename = filename
  2773. self.save_project()
  2774. self.setWindowTitle("Carla - %s" % os.path.basename(self.m_project_filename))
  2775. else:
  2776. self.save_project()
  2777. @pyqtSlot()
  2778. def slot_file_save_as(self):
  2779. self.slot_file_save(True)
  2780. @pyqtSlot()
  2781. def slot_plugin_add(self):
  2782. dialog = PluginDatabaseW(self)
  2783. if dialog.exec_():
  2784. btype = dialog.ret_plugin['build']
  2785. ptype = dialog.ret_plugin['type']
  2786. filename = dialog.ret_plugin['binary']
  2787. label = dialog.ret_plugin['label']
  2788. extra_stuff = self.get_extra_stuff(dialog.ret_plugin)
  2789. self.add_plugin(btype, ptype, filename, label, extra_stuff, True)
  2790. @pyqtSlot()
  2791. def slot_remove_all(self):
  2792. for i in range(MAX_PLUGINS):
  2793. if self.m_plugin_list[i]:
  2794. self.remove_plugin(i, False)
  2795. @pyqtSlot()
  2796. def slot_configureCarla(self):
  2797. dialog = SettingsW(self, "carla")
  2798. if dialog.exec_():
  2799. self.loadSettings(False)
  2800. for pwidget in self.m_plugin_list:
  2801. if pwidget:
  2802. pwidget.peak_in.setRefreshRate(self.m_savedSettings["Main/RefreshInterval"])
  2803. pwidget.peak_out.setRefreshRate(self.m_savedSettings["Main/RefreshInterval"])
  2804. @pyqtSlot()
  2805. def slot_aboutCarla(self):
  2806. CarlaAboutW(self).exec_()
  2807. def saveSettings(self):
  2808. self.settings.setValue("Geometry", self.saveGeometry())
  2809. self.settings.setValue("ShowToolbar", self.toolBar.isVisible())
  2810. def loadSettings(self, geometry):
  2811. if geometry:
  2812. self.restoreGeometry(self.settings.value("Geometry", ""))
  2813. show_toolbar = self.settings.value("ShowToolbar", True, type=bool)
  2814. self.act_settings_show_toolbar.setChecked(show_toolbar)
  2815. self.toolBar.setVisible(show_toolbar)
  2816. self.m_savedSettings = {
  2817. "Main/DefaultProjectFolder": self.settings.value("Main/DefaultProjectFolder", DEFAULT_PROJECT_FOLDER, type=str),
  2818. "Main/RefreshInterval": self.settings.value("Main/RefreshInterval", 120, type=int)
  2819. }
  2820. global LADSPA_PATH, DSSI_PATH, LV2_PATH, VST_PATH, GIG_PATH, SF2_PATH, SFZ_PATH
  2821. LADSPA_PATH = toList(self.settings.value("Paths/LADSPA", LADSPA_PATH))
  2822. DSSI_PATH = toList(self.settings.value("Paths/DSSI", DSSI_PATH))
  2823. LV2_PATH = toList(self.settings.value("Paths/LV2", LV2_PATH))
  2824. VST_PATH = toList(self.settings.value("Paths/VST", VST_PATH))
  2825. GIG_PATH = toList(self.settings.value("Paths/GIG", GIG_PATH))
  2826. SF2_PATH = toList(self.settings.value("Paths/SF2", SF2_PATH))
  2827. SFZ_PATH = toList(self.settings.value("Paths/SFZ", SFZ_PATH))
  2828. CarlaHost.set_option(OPTION_PATH_LADSPA, 0, splitter.join(LADSPA_PATH))
  2829. CarlaHost.set_option(OPTION_PATH_DSSI, 0, splitter.join(DSSI_PATH))
  2830. CarlaHost.set_option(OPTION_PATH_LV2, 0, splitter.join(LV2_PATH))
  2831. CarlaHost.set_option(OPTION_PATH_VST, 0, splitter.join(VST_PATH))
  2832. CarlaHost.set_option(OPTION_PATH_GIG, 0, splitter.join(GIG_PATH))
  2833. CarlaHost.set_option(OPTION_PATH_SF2, 0, splitter.join(SF2_PATH))
  2834. CarlaHost.set_option(OPTION_PATH_SFZ, 0, splitter.join(SFZ_PATH))
  2835. def timerEvent(self, event):
  2836. if event.timerId() == self.TIMER_GUI_STUFF:
  2837. for pwidget in self.m_plugin_list:
  2838. if pwidget: pwidget.check_gui_stuff()
  2839. CarlaHost.idle_guis()
  2840. elif event.timerId() == self.TIMER_GUI_STUFF2:
  2841. for pwidget in self.m_plugin_list:
  2842. if pwidget: pwidget.check_gui_stuff2()
  2843. QMainWindow.timerEvent(self, event)
  2844. def closeEvent(self, event):
  2845. self.saveSettings()
  2846. self.slot_remove_all()
  2847. QMainWindow.closeEvent(self, event)
  2848. #--------------- main ------------------
  2849. if __name__ == '__main__':
  2850. # App initialization
  2851. app = QApplication(sys.argv)
  2852. app.setApplicationName("Carla")
  2853. app.setApplicationVersion(VERSION)
  2854. app.setOrganizationName("Cadence")
  2855. app.setWindowIcon(QIcon(":/scalable/carla.svg"))
  2856. lib_prefix = None
  2857. project_filename = None
  2858. for i in range(len(app.arguments())):
  2859. if i == 0: continue
  2860. argument = app.arguments()[i]
  2861. if argument.startswith("--with-libprefix="):
  2862. lib_prefix = argument.replace("--with-libprefix=", "")
  2863. elif (os.path.exists(argument)):
  2864. project_filename = argument
  2865. #style = app.style().metaObject().className()
  2866. #force_parameters_style = (style in ("Bespin::Style",))
  2867. CarlaHost = Host(lib_prefix)
  2868. # Create GUI and read settings
  2869. gui = CarlaMainW()
  2870. # Init backend
  2871. CarlaHost.set_option(OPTION_GLOBAL_JACK_CLIENT, gui.settings.value("Engine/GlobalClient", False, type=bool), "")
  2872. CarlaHost.set_option(OPTION_USE_DSSI_CHUNKS, gui.settings.value("Engine/DSSIChunks", False, type=bool), "")
  2873. CarlaHost.set_option(OPTION_PREFER_UI_BRIDGES, gui.settings.value("Engine/PreferBridges", True, type=bool), "")
  2874. if carla_bridge_unix32:
  2875. CarlaHost.set_option(OPTION_PATH_BRIDGE_UNIX32, 0, carla_bridge_unix32)
  2876. if carla_bridge_unix64:
  2877. CarlaHost.set_option(OPTION_PATH_BRIDGE_UNIX64, 0, carla_bridge_unix64)
  2878. if carla_bridge_win32:
  2879. CarlaHost.set_option(OPTION_PATH_BRIDGE_WIN32, 0, carla_bridge_win32)
  2880. if carla_bridge_win64:
  2881. CarlaHost.set_option(OPTION_PATH_BRIDGE_WIN64, 0, carla_bridge_win64)
  2882. if carla_bridge_lv2_gtk2:
  2883. CarlaHost.set_option(OPTION_PATH_BRIDGE_LV2_GTK2, 0, carla_bridge_lv2_gtk2)
  2884. if carla_bridge_lv2_qt4:
  2885. CarlaHost.set_option(OPTION_PATH_BRIDGE_LV2_QT4, 0, carla_bridge_lv2_qt4)
  2886. if carla_bridge_lv2_x11:
  2887. CarlaHost.set_option(OPTION_PATH_BRIDGE_LV2_X11, 0, carla_bridge_lv2_x11)
  2888. if carla_bridge_vst_x11:
  2889. CarlaHost.set_option(OPTION_PATH_BRIDGE_VST_X11, 0, carla_bridge_vst_x11)
  2890. if not CarlaHost.engine_init("Carla"):
  2891. CustomMessageBox(None, QMessageBox.Critical, "Error", "Could not connect to JACK",
  2892. cString(CarlaHost.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)
  2893. sys.exit(1)
  2894. # Set-up custom signal handling
  2895. set_up_signals(gui)
  2896. # Show GUI
  2897. gui.show()
  2898. if project_filename:
  2899. gui.m_project_filename = project_filename
  2900. gui.load_project()
  2901. gui.setWindowTitle("Carla - %s" % os.path.basename(project_filename))
  2902. # App-Loop
  2903. ret = app.exec_()
  2904. # Close Host
  2905. if CarlaHost.is_engine_running() and not CarlaHost.engine_close():
  2906. print(cString(CarlaHost.get_last_error()))
  2907. # Exit properly
  2908. sys.exit(ret)