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.

3411 lines
130KB

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