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.

2800 lines
111KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # LADISH frontend
  4. # Copyright (C) 2010-2018 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the COPYING file
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. from time import ctime
  20. if True:
  21. from PyQt5.QtCore import QPointF
  22. from PyQt5.QtWidgets import QAction, QApplication, QCheckBox, QHBoxLayout, QVBoxLayout, QTableWidgetItem, QTreeWidgetItem
  23. else:
  24. from PyQt4.QtCore import QPointF
  25. from PyQt4.QtGui import QAction, QApplication, QCheckBox, QHBoxLayout, QVBoxLayout, QTableWidgetItem, QTreeWidgetItem
  26. # ------------------------------------------------------------------------------------------------------------
  27. # Imports (Custom Stuff)
  28. import claudia_launcher
  29. import systray
  30. import ui_claudia
  31. import ui_claudia_studioname
  32. import ui_claudia_studiolist
  33. import ui_claudia_createroom
  34. import ui_claudia_projectname
  35. import ui_claudia_projectproperties
  36. import ui_claudia_runcustom
  37. from shared_canvasjack import *
  38. from shared_settings import *
  39. from shared_i18n import *
  40. # ------------------------------------------------------------------------------------------------------------
  41. # Try Import DBus
  42. try:
  43. import dbus
  44. from dbus.mainloop.pyqt5 import DBusMainLoop
  45. haveDBus = True
  46. except:
  47. try:
  48. # Try falling back to GMainLoop
  49. from dbus.mainloop.glib import DBusGMainLoop as DBusMainLoop
  50. haveDBus = True
  51. except:
  52. haveDBus = False
  53. # ------------------------------------------------------------------------------------------------------------
  54. # Try Import OpenGL
  55. try:
  56. from PyQt5.QtOpenGL import QGLWidget
  57. hasGL = True
  58. except:
  59. hasGL = False
  60. # ------------------------------------------------------------------------------------------------------------
  61. # Static Variables
  62. # NOTE - set to true when supported
  63. USE_CLAUDIA_ADD_NEW = True
  64. # internal indexes
  65. iConnId = 0
  66. iConnOutput = 1
  67. iConnInput = 2
  68. iAppCommand = 0
  69. iAppName = 1
  70. iAppTerminal = 2
  71. iAppLevel = 3
  72. iAppActive = 4
  73. iAppPropName = 0
  74. iAppPropDescription = 1
  75. iAppPropNotes = 2
  76. iAppPropSaveNow = 3
  77. iItemPropNumber = 0
  78. iItemPropName = 1
  79. iItemPropActive = 2
  80. iItemPropTerminal = 3
  81. iItemPropLevel = 4
  82. iItemPropRoomPath = 0
  83. iItemPropRoomName = 1
  84. # jackdbus indexes
  85. iGraphVersion = 0
  86. iJackClientId = 1
  87. iJackClientName = 2
  88. iJackPortId = 3
  89. iJackPortName = 4
  90. iJackPortNewName = 5
  91. iJackPortFlags = 5
  92. iJackPortType = 6
  93. iRenamedId = 1
  94. iRenamedOldName = 2
  95. iRenamedNewName = 3
  96. iSourceClientId = 1
  97. iSourceClientName = 2
  98. iSourcePortId = 3
  99. iSourcePortName = 4
  100. iTargetClientId = 5
  101. iTargetClientName = 6
  102. iTargetPortId = 7
  103. iTargetPortName = 8
  104. iJackConnId = 9
  105. # ladish indexes
  106. iStudioListName = 0
  107. iStudioListDict = 1
  108. iStudioRenamedName = 0
  109. iRoomAppearedPath = 0
  110. iRoomAppearedDict = 1
  111. iProjChangedId = 0
  112. iProjChangedDict = 1
  113. iAppChangedNumber = 1
  114. iAppChangedName = 2
  115. iAppChangedActive = 3
  116. iAppChangedTerminal = 4
  117. iAppChangedLevel = 5
  118. # internal defines
  119. ITEM_TYPE_NULL = 0
  120. ITEM_TYPE_STUDIO = 1
  121. ITEM_TYPE_STUDIO_APP = 2
  122. ITEM_TYPE_ROOM = 3
  123. ITEM_TYPE_ROOM_APP = 4
  124. # C defines
  125. JACKDBUS_PORT_FLAG_INPUT = 0x01
  126. JACKDBUS_PORT_FLAG_OUTPUT = 0x02
  127. JACKDBUS_PORT_FLAG_PHYSICAL = 0x04
  128. JACKDBUS_PORT_FLAG_CAN_MONITOR = 0x08
  129. JACKDBUS_PORT_FLAG_TERMINAL = 0x10
  130. JACKDBUS_PORT_TYPE_AUDIO = 0
  131. JACKDBUS_PORT_TYPE_MIDI = 1
  132. GRAPH_DICT_OBJECT_TYPE_GRAPH = 0
  133. GRAPH_DICT_OBJECT_TYPE_CLIENT = 1
  134. GRAPH_DICT_OBJECT_TYPE_PORT = 2
  135. GRAPH_DICT_OBJECT_TYPE_CONNECTION = 3
  136. URI_A2J_PORT = "http://ladish.org/ns/a2j"
  137. URI_CANVAS_WIDTH = "http://ladish.org/ns/canvas/width"
  138. URI_CANVAS_HEIGHT = "http://ladish.org/ns/canvas/height"
  139. URI_CANVAS_X = "http://ladish.org/ns/canvas/x"
  140. URI_CANVAS_Y = "http://ladish.org/ns/canvas/y"
  141. URI_CANVAS_SPLIT = "http://kxstudio.sf.net/ns/canvas/split"
  142. URI_CANVAS_X_SPLIT = "http://kxstudio.sf.net/ns/canvas/x_split"
  143. URI_CANVAS_Y_SPLIT = "http://kxstudio.sf.net/ns/canvas/y_split"
  144. URI_CANVAS_ICON = "http://kxstudio.sf.net/ns/canvas/icon"
  145. DEFAULT_CANVAS_WIDTH = 3100
  146. DEFAULT_CANVAS_HEIGHT = 2400
  147. RECENT_PROJECTS_STORE_MAX_ITEMS = 50
  148. # ------------------------------------------------------------------------------------------------------------
  149. # Set default project folder
  150. DEFAULT_PROJECT_FOLDER = os.path.join(HOME, "ladish-projects")
  151. setDefaultProjectFolder(DEFAULT_PROJECT_FOLDER)
  152. # ------------------------------------------------------------------------------------------------------------
  153. # Studio Name Dialog
  154. class StudioNameW(QDialog):
  155. NEW = 1
  156. RENAME = 2
  157. SAVE_AS = 3
  158. def __init__(self, parent, mode):
  159. QDialog.__init__(self, parent)
  160. self.ui = ui_claudia_studioname.Ui_StudioNameW()
  161. self.ui.setupUi(self)
  162. self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
  163. if mode == self.NEW:
  164. self.setWindowTitle(self.tr("New studio"))
  165. elif mode == self.RENAME:
  166. self.setWindowTitle(self.tr("Rename studio"))
  167. elif mode == self.SAVE_AS:
  168. self.setWindowTitle(self.tr("Save studio as"))
  169. self.fMode = mode
  170. self.fStudioList = []
  171. if mode == self.RENAME and bool(gDBus.ladish_control.IsStudioLoaded()):
  172. currentName = str(gDBus.ladish_studio.GetName())
  173. self.fStudioList.append(currentName)
  174. self.ui.le_name.setText(currentName)
  175. studioList = gDBus.ladish_control.GetStudioList()
  176. for studio in studioList:
  177. self.fStudioList.append(str(studio[iStudioListName]))
  178. self.accepted.connect(self.slot_setReturn)
  179. self.ui.le_name.textChanged.connect(self.slot_checkText)
  180. self.fRetStudioName = ""
  181. @pyqtSlot(str)
  182. def slot_checkText(self, text):
  183. if self.fMode == self.SAVE_AS:
  184. check = bool(text)
  185. else:
  186. check = bool(text and text not in self.fStudioList)
  187. self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(check)
  188. @pyqtSlot()
  189. def slot_setReturn(self):
  190. self.fRetStudioName = self.ui.le_name.text()
  191. def done(self, r):
  192. QDialog.done(self, r)
  193. self.close()
  194. # Studio List Dialog
  195. class StudioListW(QDialog, ui_claudia_studiolist.Ui_StudioListW):
  196. def __init__(self, parent):
  197. QDialog.__init__(self, parent)
  198. self.setupUi(self)
  199. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
  200. self.tableWidget.setColumnWidth(0, 125)
  201. index = 0
  202. studio_list = gDBus.ladish_control.GetStudioList()
  203. for studio in studio_list:
  204. name = str(studio[iStudioListName])
  205. date = ctime(float(studio[iStudioListDict]["Modification Time"]))
  206. w_name = QTableWidgetItem(name)
  207. w_date = QTableWidgetItem(date)
  208. self.tableWidget.insertRow(index)
  209. self.tableWidget.setItem(index, 0, w_name)
  210. self.tableWidget.setItem(index, 1, w_date)
  211. index += 1
  212. self.accepted.connect(self.slot_setReturn)
  213. self.tableWidget.cellDoubleClicked.connect(self.accept)
  214. self.tableWidget.currentCellChanged.connect(self.slot_checkSelection)
  215. if self.tableWidget.rowCount() > 0:
  216. self.tableWidget.setCurrentCell(0, 0)
  217. self.ret_studio_name = ""
  218. @pyqtSlot(int)
  219. def slot_checkSelection(self, row):
  220. check = bool(row >= 0)
  221. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(check)
  222. @pyqtSlot()
  223. def slot_setReturn(self):
  224. if self.tableWidget.rowCount() >= 0:
  225. self.ret_studio_name = self.tableWidget.item(self.tableWidget.currentRow(), 0).text()
  226. def done(self, r):
  227. QDialog.done(self, r)
  228. self.close()
  229. # Create Room Dialog
  230. class CreateRoomW(QDialog, ui_claudia_createroom.Ui_CreateRoomW):
  231. def __init__(self, parent):
  232. QDialog.__init__(self, parent)
  233. self.setupUi(self)
  234. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
  235. templates_list = gDBus.ladish_control.GetRoomTemplateList()
  236. for template_name, template_dict in templates_list:
  237. self.lw_templates.addItem(template_name)
  238. self.accepted.connect(self.slot_setReturn)
  239. self.le_name.textChanged.connect(self.slot_checkText)
  240. if self.lw_templates.count() > 0:
  241. self.lw_templates.setCurrentRow(0)
  242. self.ret_room_name = ""
  243. self.ret_room_template = ""
  244. @pyqtSlot(str)
  245. def slot_checkText(self, text):
  246. check = bool(text and self.lw_templates.currentRow() >= 0)
  247. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(check)
  248. @pyqtSlot()
  249. def slot_setReturn(self):
  250. if self.lw_templates.count() > 0:
  251. self.ret_room_name = self.le_name.text()
  252. self.ret_room_template = self.lw_templates.currentItem().text()
  253. def done(self, r):
  254. QDialog.done(self, r)
  255. self.close()
  256. # Project Name Dialog
  257. class ProjectNameW(QDialog, ui_claudia_projectname.Ui_ProjectNameW):
  258. NEW = 1
  259. SAVE_AS = 2
  260. def __init__(self, parent, mode, proj_folder, path="", name=""):
  261. QDialog.__init__(self, parent)
  262. self.setupUi(self)
  263. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
  264. if mode == self.NEW:
  265. self.setWindowTitle(self.tr("New project"))
  266. elif mode == self.SAVE_AS:
  267. self.setWindowTitle(self.tr("Save project as"))
  268. self.le_path.setText(path)
  269. self.le_name.setText(name)
  270. self.checkText(path, name)
  271. self.m_proj_folder = proj_folder
  272. self.accepted.connect(self.slot_setReturn)
  273. self.b_open.clicked.connect(self.slot_checkFolder)
  274. self.le_path.textChanged.connect(self.slot_checkText_path)
  275. self.le_name.textChanged.connect(self.slot_checkText_name)
  276. self.ret_project_name = ""
  277. self.ret_project_path = ""
  278. def checkText(self, name, path):
  279. check = bool(name and path and os.path.exists(path) and os.path.isdir(path))
  280. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(check)
  281. @pyqtSlot()
  282. def slot_checkFolder(self):
  283. # Create default project folder if the project has not been set yet
  284. if not self.le_path.text():
  285. if not os.path.exists(self.m_proj_folder):
  286. os.mkdir(self.m_proj_folder)
  287. if self.le_path.text():
  288. proj_path = self.le_path.text()
  289. else:
  290. proj_path = self.m_proj_folder
  291. getAndSetPath(self, proj_path, self.le_path)
  292. @pyqtSlot(str)
  293. def slot_checkText_name(self, text):
  294. self.checkText(text, self.le_path.text())
  295. @pyqtSlot(str)
  296. def slot_checkText_path(self, text):
  297. self.checkText(self.le_name.text(), text)
  298. @pyqtSlot()
  299. def slot_setReturn(self):
  300. self.ret_project_name = self.le_name.text()
  301. self.ret_project_path = self.le_path.text()
  302. def done(self, r):
  303. QDialog.done(self, r)
  304. self.close()
  305. # Project Properties Dialog
  306. class ProjectPropertiesW(QDialog, ui_claudia_projectproperties.Ui_ProjectPropertiesW):
  307. def __init__(self, parent, name, description, notes):
  308. QDialog.__init__(self, parent)
  309. self.setupUi(self)
  310. self.m_default_name = name
  311. self.m_last_name = name
  312. self.accepted.connect(self.slot_setReturn)
  313. self.le_name.textChanged.connect(self.slot_checkText_name)
  314. self.cb_save_now.clicked.connect(self.slot_checkSaveNow)
  315. self.le_name.setText(name)
  316. self.le_description.setText(description)
  317. self.le_notes.setPlainText(notes)
  318. self.ret_obj = None
  319. @pyqtSlot()
  320. def slot_setReturn(self):
  321. self.ret_obj = [None, None, None, None]
  322. self.ret_obj[iAppPropName] = self.le_name.text()
  323. self.ret_obj[iAppPropDescription] = self.le_description.text()
  324. self.ret_obj[iAppPropNotes] = self.le_notes.toPlainText() # plainText()
  325. self.ret_obj[iAppPropSaveNow] = self.cb_save_now.isChecked()
  326. @pyqtSlot(bool)
  327. def slot_checkSaveNow(self, save):
  328. if save:
  329. self.le_name.setText(self.m_last_name)
  330. else:
  331. self.m_last_name = self.le_name.text()
  332. self.le_name.setText(self.m_default_name)
  333. @pyqtSlot(str)
  334. def slot_checkText_name(self, text):
  335. check = bool(text)
  336. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(check)
  337. def done(self, r):
  338. QDialog.done(self, r)
  339. self.close()
  340. # Run Custom App Dialog
  341. class RunCustomW(QDialog, ui_claudia_runcustom.Ui_RunCustomW):
  342. def __init__(self, parent, isRoom, app_obj=None):
  343. QDialog.__init__(self, parent)
  344. self.setupUi(self)
  345. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(bool(app_obj))
  346. if app_obj:
  347. self.le_command.setText(app_obj[iAppCommand])
  348. self.le_name.setText(app_obj[iAppName])
  349. self.cb_terminal.setChecked(app_obj[iAppTerminal])
  350. level = app_obj[iAppLevel]
  351. if level == "0":
  352. self.rb_level_0.setChecked(True)
  353. elif level == "1":
  354. self.rb_level_1.setChecked(True)
  355. elif level == "lash":
  356. self.rb_level_lash.setChecked(True)
  357. elif level == "jacksession":
  358. self.rb_level_js.setChecked(True)
  359. else:
  360. self.rb_level_0.setChecked(True)
  361. if app_obj[iAppActive]:
  362. self.le_command.setEnabled(False)
  363. self.cb_terminal.setEnabled(False)
  364. self.rb_level_0.setEnabled(False)
  365. self.rb_level_1.setEnabled(False)
  366. self.rb_level_lash.setEnabled(False)
  367. self.rb_level_js.setEnabled(False)
  368. else:
  369. self.rb_level_0.setChecked(True)
  370. if not isRoom:
  371. self.rb_level_lash.setEnabled(False)
  372. self.rb_level_js.setEnabled(False)
  373. self.accepted.connect(self.slot_setReturn)
  374. self.le_command.textChanged.connect(self.slot_checkText)
  375. self.ret_app_obj = None
  376. @pyqtSlot(str)
  377. def slot_checkText(self, text):
  378. check = bool(text)
  379. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(check)
  380. @pyqtSlot()
  381. def slot_setReturn(self):
  382. if self.rb_level_0.isChecked():
  383. level = "0"
  384. elif self.rb_level_1.isChecked():
  385. level = "1"
  386. elif self.rb_level_lash.isChecked():
  387. level = "lash"
  388. elif self.rb_level_js.isChecked():
  389. level = "jacksession"
  390. else:
  391. return
  392. self.ret_app_obj = [None, None, None, None, None]
  393. self.ret_app_obj[iAppCommand] = self.le_command.text()
  394. self.ret_app_obj[iAppName] = self.le_name.text()
  395. self.ret_app_obj[iAppTerminal] = self.cb_terminal.isChecked()
  396. self.ret_app_obj[iAppLevel] = level
  397. self.ret_app_obj[iAppActive] = False
  398. def done(self, r):
  399. QDialog.done(self, r)
  400. self.close()
  401. # Add Application Dialog
  402. class ClaudiaLauncherW(QDialog):
  403. def __init__(self, parent, appBus, proj_folder, is_room, bpm, sample_rate):
  404. QDialog.__init__(self, parent)
  405. self.launcher = claudia_launcher.ClaudiaLauncher(self)
  406. self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Close, Qt.Horizontal, self)
  407. self.checkBox = QCheckBox(self)
  408. self.checkBox.setText(self.tr("Auto-close"))
  409. self.checkBox.setChecked(True)
  410. self.layoutV = QVBoxLayout(self)
  411. self.layoutH = QHBoxLayout()
  412. #if QDialogButtonBox.ButtonLayout:
  413. self.layoutH.addWidget(self.checkBox)
  414. self.layoutH.addWidget(self.buttonBox)
  415. #else:
  416. #self.layoutH.addWidget(self.buttonBox)
  417. #self.layoutH.addWidget(self.checkBox)
  418. self.layoutV.addWidget(self.launcher)
  419. self.layoutV.addLayout(self.layoutH)
  420. self.settings = QSettings("Cadence", "Claudia-Launcher")
  421. self.launcher.setCallbackApp(self, self.settings, True)
  422. self.loadSettings()
  423. self.setWindowTitle("Claudia Launcher")
  424. self.m_appBus = appBus
  425. self.m_proj_folder = proj_folder
  426. self.m_is_room = is_room
  427. self.m_bpm = bpm
  428. self.m_sampleRate = sample_rate
  429. self.test_url = True
  430. self.test_selected = False
  431. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
  432. self.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.slot_addAppToLADISH)
  433. self.buttonBox.button(QDialogButtonBox.Close).clicked.connect(self.reject)
  434. # ----------------------------------------
  435. # Callbacks
  436. def callback_checkGUI(self, test_selected=None):
  437. if test_selected != None:
  438. self.test_selected = test_selected
  439. if self.test_url and self.test_selected:
  440. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
  441. else:
  442. self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
  443. def callback_getProjectFolder(self):
  444. return self.m_proj_folder
  445. def callback_getAppBus(self):
  446. return self.m_appBus
  447. def callback_getBPM(self):
  448. if self.m_bpm < 30:
  449. return 120.0
  450. else:
  451. return self.m_bpm
  452. def callback_getSampleRate(self):
  453. return self.m_sampleRate
  454. def callback_isLadishRoom(self):
  455. return self.m_is_room
  456. # ----------------------------------------
  457. @pyqtSlot()
  458. def slot_addAppToLADISH(self):
  459. self.launcher.addAppToLADISH()
  460. if self.checkBox.isChecked():
  461. self.accept()
  462. def saveSettings(self):
  463. self.settings.setValue("Geometry", self.saveGeometry())
  464. self.launcher.saveSettings()
  465. def loadSettings(self):
  466. if self.settings.contains("Geometry"):
  467. self.restoreGeometry(self.settings.value("Geometry", b""))
  468. else:
  469. self.resize(850, 500)
  470. self.launcher.loadSettings()
  471. def closeEvent(self, event):
  472. self.saveSettings()
  473. QDialog.closeEvent(self, event)
  474. def done(self, r):
  475. QDialog.done(self, r)
  476. self.close()
  477. # ------------------------------------------------------------------------------------------------------------
  478. # Claudia Main Window
  479. class ClaudiaMainW(AbstractCanvasJackClass):
  480. DBusCrashCallback = pyqtSignal(str)
  481. DBusServerStartedCallback = pyqtSignal()
  482. DBusServerStoppedCallback = pyqtSignal()
  483. DBusClientAppearedCallback = pyqtSignal(int, str)
  484. DBusClientDisappearedCallback = pyqtSignal(int)
  485. DBusClientRenamedCallback = pyqtSignal(int, str)
  486. DBusPortAppearedCallback = pyqtSignal(int, int, str, int, int)
  487. DBusPortDisppearedCallback = pyqtSignal(int)
  488. DBusPortRenamedCallback = pyqtSignal(int, str)
  489. DBusPortsConnectedCallback = pyqtSignal(int, int, int)
  490. DBusPortsDisconnectedCallback = pyqtSignal(int)
  491. DBusStudioAppearedCallback = pyqtSignal()
  492. DBusStudioDisappearedCallback = pyqtSignal()
  493. DBusQueueExecutionHaltedCallback = pyqtSignal()
  494. DBusCleanExitCallback = pyqtSignal()
  495. DBusStudioStartedCallback = pyqtSignal()
  496. DBusStudioStoppedCallback = pyqtSignal()
  497. DBusStudioRenamedCallback = pyqtSignal(str)
  498. DBusStudioCrashedCallback = pyqtSignal()
  499. DBusRoomAppearedCallback = pyqtSignal(str, str)
  500. DBusRoomDisappearedCallback = pyqtSignal(str)
  501. DBusRoomChangedCallback = pyqtSignal()
  502. DBusProjectPropertiesChanged = pyqtSignal(str, str)
  503. DBusAppAdded2Callback = pyqtSignal(str, int, str, bool, bool, str)
  504. DBusAppRemovedCallback = pyqtSignal(str, int)
  505. DBusAppStateChanged2Callback = pyqtSignal(str, int, str, bool, bool, str)
  506. def __init__(self, parent=None):
  507. AbstractCanvasJackClass.__init__(self, "Claudia", ui_claudia.Ui_ClaudiaMainW, parent)
  508. self.m_lastItemType = None
  509. self.m_lastRoomPath = None
  510. self.m_crashedJACK = False
  511. self.m_crashedLADISH = False
  512. self.loadSettings(True)
  513. # -------------------------------------------------------------
  514. # Set-up GUI
  515. setIcons(self, ["canvas", "jack", "transport"])
  516. self.ui.act_studio_new.setIcon(getIcon("document-new"))
  517. self.ui.menu_studio_load.setIcon(getIcon("document-open"))
  518. self.ui.act_studio_start.setIcon(getIcon("media-playback-start"))
  519. self.ui.act_studio_stop.setIcon(getIcon("media-playback-stop"))
  520. self.ui.act_studio_rename.setIcon(getIcon("edit-rename"))
  521. self.ui.act_studio_save.setIcon(getIcon("document-save"))
  522. self.ui.act_studio_save_as.setIcon(getIcon("document-save-as"))
  523. self.ui.act_studio_unload.setIcon(getIcon("window-close"))
  524. self.ui.menu_studio_delete.setIcon(getIcon("edit-delete"))
  525. self.ui.b_studio_new.setIcon(getIcon("document-new"))
  526. self.ui.b_studio_load.setIcon(getIcon("document-open"))
  527. self.ui.b_studio_save.setIcon(getIcon("document-save"))
  528. self.ui.b_studio_save_as.setIcon(getIcon("document-save-as"))
  529. self.ui.b_studio_start.setIcon(getIcon("media-playback-start"))
  530. self.ui.b_studio_stop.setIcon(getIcon("media-playback-stop"))
  531. self.ui.act_room_create.setIcon(getIcon("list-add"))
  532. self.ui.menu_room_delete.setIcon(getIcon("edit-delete"))
  533. self.ui.act_project_new.setIcon(getIcon("document-new"))
  534. self.ui.menu_project_load.setIcon(getIcon("document-open"))
  535. self.ui.act_project_save.setIcon(getIcon("document-save"))
  536. self.ui.act_project_save_as.setIcon(getIcon("document-save-as"))
  537. self.ui.act_project_unload.setIcon(getIcon("window-close"))
  538. self.ui.act_project_properties.setIcon(getIcon("edit-rename"))
  539. self.ui.b_project_new.setIcon(getIcon("document-new"))
  540. self.ui.b_project_load.setIcon(getIcon("document-open"))
  541. self.ui.b_project_save.setIcon(getIcon("document-save"))
  542. self.ui.b_project_save_as.setIcon(getIcon("document-save-as"))
  543. self.ui.act_app_add_new.setIcon(getIcon("list-add"))
  544. self.ui.act_app_run_custom.setIcon(getIcon("system-run"))
  545. self.ui.act_tools_reactivate_ladishd.setIcon(getIcon("view-refresh"))
  546. self.ui.act_quit.setIcon(getIcon("application-exit"))
  547. self.ui.act_settings_configure.setIcon(getIcon("configure"))
  548. self.ui.cb_buffer_size.clear()
  549. self.ui.cb_sample_rate.clear()
  550. for bufferSize in BUFFER_SIZE_LIST:
  551. self.ui.cb_buffer_size.addItem(str(bufferSize))
  552. for sampleRate in SAMPLE_RATE_LIST:
  553. self.ui.cb_sample_rate.addItem(str(sampleRate))
  554. # -------------------------------------------------------------
  555. # Set-up Systray
  556. if self.fSavedSettings["Main/UseSystemTray"]:
  557. self.systray = systray.GlobalSysTray(self, "Claudia", "claudia")
  558. self.systray.addAction("studio_new", self.tr("New Studio..."))
  559. self.systray.addSeparator("sep1")
  560. self.systray.addAction("studio_start", self.tr("Start Studio"))
  561. self.systray.addAction("studio_stop", self.tr("Stop Studio"))
  562. self.systray.addSeparator("sep2")
  563. self.systray.addAction("studio_save", self.tr("Save Studio"))
  564. self.systray.addAction("studio_save_as", self.tr("Save Studio As..."))
  565. self.systray.addAction("studio_rename", self.tr("Rename Studio..."))
  566. self.systray.addAction("studio_unload", self.tr("Unload Studio"))
  567. self.systray.addSeparator("sep3")
  568. self.systray.addMenu("tools", self.tr("Tools"))
  569. self.systray.addMenuAction("tools", "tools_configure_jack", self.tr("Configure JACK"))
  570. self.systray.addMenuAction("tools", "tools_render", self.tr("JACK Render"))
  571. self.systray.addMenuAction("tools", "tools_logs", self.tr("Logs"))
  572. self.systray.addMenuSeparator("tools", "tools_sep")
  573. self.systray.addMenuAction("tools", "tools_clear_xruns", self.tr("Clear Xruns"))
  574. self.systray.addAction("configure", self.tr("Configure Claudia"))
  575. self.systray.setActionIcon("studio_new", "document-new")
  576. self.systray.setActionIcon("studio_start", "media-playback-start")
  577. self.systray.setActionIcon("studio_stop", "media-playback-stop")
  578. self.systray.setActionIcon("studio_save", "document-save")
  579. self.systray.setActionIcon("studio_save_as", "document-save-as")
  580. self.systray.setActionIcon("studio_rename", "edit-rename")
  581. self.systray.setActionIcon("studio_unload", "dialog-close")
  582. self.systray.setActionIcon("tools_configure_jack", "configure")
  583. self.systray.setActionIcon("tools_render", "media-record")
  584. self.systray.setActionIcon("tools_clear_xruns", "edit-clear")
  585. self.systray.setActionIcon("configure", "configure")
  586. self.systray.connect("studio_new", self.slot_studio_new)
  587. self.systray.connect("studio_start", self.slot_studio_start)
  588. self.systray.connect("studio_stop", self.slot_studio_stop)
  589. self.systray.connect("studio_save", self.slot_studio_save)
  590. self.systray.connect("studio_save_as", self.slot_studio_save_as)
  591. self.systray.connect("studio_rename", self.slot_studio_rename)
  592. self.systray.connect("studio_unload", self.slot_studio_unload)
  593. self.systray.connect("tools_configure_jack", self.slot_showJackSettings)
  594. self.systray.connect("tools_render", self.slot_showRender)
  595. self.systray.connect("tools_logs", self.slot_showLogs)
  596. self.systray.connect("tools_clear_xruns", self.slot_JackClearXruns)
  597. self.systray.connect("configure", self.slot_configureClaudia)
  598. self.systray.setToolTip("LADISH Frontend")
  599. self.systray.show()
  600. else:
  601. self.systray = None
  602. # -------------------------------------------------------------
  603. # Set-up Canvas
  604. self.scene = patchcanvas.PatchScene(self, self.ui.graphicsView)
  605. self.ui.graphicsView.setScene(self.scene)
  606. self.ui.graphicsView.setRenderHint(QPainter.Antialiasing, bool(self.fSavedSettings["Canvas/Antialiasing"] == patchcanvas.ANTIALIASING_FULL))
  607. if self.fSavedSettings["Canvas/UseOpenGL"] and hasGL:
  608. self.ui.graphicsView.setViewport(QGLWidget(self.ui.graphicsView))
  609. self.ui.graphicsView.setRenderHint(QPainter.HighQualityAntialiasing, self.fSavedSettings["Canvas/HighQualityAntialiasing"])
  610. pOptions = patchcanvas.options_t()
  611. pOptions.theme_name = self.fSavedSettings["Canvas/Theme"]
  612. pOptions.auto_hide_groups = self.fSavedSettings["Canvas/AutoHideGroups"]
  613. pOptions.use_bezier_lines = self.fSavedSettings["Canvas/UseBezierLines"]
  614. pOptions.antialiasing = self.fSavedSettings["Canvas/Antialiasing"]
  615. pOptions.eyecandy = self.fSavedSettings["Canvas/EyeCandy"]
  616. pFeatures = patchcanvas.features_t()
  617. pFeatures.group_info = False
  618. pFeatures.group_rename = True
  619. pFeatures.port_info = True
  620. pFeatures.port_rename = True
  621. pFeatures.handle_group_pos = False
  622. patchcanvas.setOptions(pOptions)
  623. patchcanvas.setFeatures(pFeatures)
  624. patchcanvas.init("Claudia", self.scene, self.canvasCallback, DEBUG)
  625. patchcanvas.setCanvasSize(0, 0, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT)
  626. patchcanvas.setInitialPos(DEFAULT_CANVAS_WIDTH / 2, DEFAULT_CANVAS_HEIGHT / 2)
  627. self.ui.graphicsView.setSceneRect(0, 0, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT)
  628. # -------------------------------------------------------------
  629. # Set-up Canvas Preview
  630. self.ui.miniCanvasPreview.setRealParent(self)
  631. self.ui.miniCanvasPreview.setViewTheme(patchcanvas.canvas.theme.canvas_bg, patchcanvas.canvas.theme.rubberband_brush, patchcanvas.canvas.theme.rubberband_pen.color())
  632. self.ui.miniCanvasPreview.init(self.scene, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT)
  633. QTimer.singleShot(100, self.slot_miniCanvasInit)
  634. # -------------------------------------------------------------
  635. # Check DBus
  636. if gDBus.jack.IsStarted():
  637. self.jackStarted()
  638. else:
  639. self.jackStopped()
  640. if gDBus.a2j:
  641. if gDBus.a2j.is_started():
  642. self.a2jStarted()
  643. else:
  644. self.a2jStopped()
  645. else:
  646. self.ui.act_tools_a2j_start.setEnabled(False)
  647. self.ui.act_tools_a2j_stop.setEnabled(False)
  648. self.ui.act_tools_a2j_export_hw.setEnabled(False)
  649. self.ui.menu_A2J_Bridge.setEnabled(False)
  650. if gDBus.ladish_control.IsStudioLoaded():
  651. self.studioLoaded()
  652. if gDBus.ladish_studio.IsStarted():
  653. self.studioStarted()
  654. self.initPorts()
  655. else:
  656. self.studioStopped()
  657. else:
  658. self.studioUnloaded()
  659. # -------------------------------------------------------------
  660. # Set-up Timers
  661. self.m_timer120 = self.startTimer(self.fSavedSettings["Main/RefreshInterval"])
  662. self.m_timer600 = self.startTimer(self.fSavedSettings["Main/RefreshInterval"] * 5)
  663. # -------------------------------------------------------------
  664. # Set-up Connections
  665. self.setCanvasConnections()
  666. self.setJackConnections(["jack", "transport", "misc"])
  667. self.ui.act_studio_new.triggered.connect(self.slot_studio_new)
  668. self.ui.act_studio_start.triggered.connect(self.slot_studio_start)
  669. self.ui.act_studio_stop.triggered.connect(self.slot_studio_stop)
  670. self.ui.act_studio_save.triggered.connect(self.slot_studio_save)
  671. self.ui.act_studio_save_as.triggered.connect(self.slot_studio_save_as)
  672. self.ui.act_studio_rename.triggered.connect(self.slot_studio_rename)
  673. self.ui.act_studio_unload.triggered.connect(self.slot_studio_unload)
  674. self.ui.act_tools_a2j_start.triggered.connect(self.slot_A2JBridgeStart)
  675. self.ui.act_tools_a2j_stop.triggered.connect(self.slot_A2JBridgeStop)
  676. self.ui.act_tools_a2j_export_hw.triggered.connect(self.slot_A2JBridgeExportHW)
  677. self.ui.b_studio_new.clicked.connect(self.slot_studio_new)
  678. self.ui.b_studio_load.clicked.connect(self.slot_studio_load_b)
  679. self.ui.b_studio_save.clicked.connect(self.slot_studio_save)
  680. self.ui.b_studio_save_as.clicked.connect(self.slot_studio_save_as)
  681. self.ui.b_studio_start.clicked.connect(self.slot_studio_start)
  682. self.ui.b_studio_stop.clicked.connect(self.slot_studio_stop)
  683. self.ui.menu_studio_load.aboutToShow.connect(self.slot_updateMenuStudioList_Load)
  684. self.ui.menu_studio_delete.aboutToShow.connect(self.slot_updateMenuStudioList_Delete)
  685. self.ui.act_room_create.triggered.connect(self.slot_room_create)
  686. self.ui.menu_room_delete.aboutToShow.connect(self.slot_updateMenuRoomList)
  687. self.ui.act_project_new.triggered.connect(self.slot_project_new)
  688. self.ui.act_project_save.triggered.connect(self.slot_project_save)
  689. self.ui.act_project_save_as.triggered.connect(self.slot_project_save_as)
  690. self.ui.act_project_unload.triggered.connect(self.slot_project_unload)
  691. self.ui.act_project_properties.triggered.connect(self.slot_project_properties)
  692. self.ui.b_project_new.clicked.connect(self.slot_project_new)
  693. self.ui.b_project_load.clicked.connect(self.slot_project_load)
  694. self.ui.b_project_save.clicked.connect(self.slot_project_save)
  695. self.ui.b_project_save_as.clicked.connect(self.slot_project_save_as)
  696. self.ui.menu_project_load.aboutToShow.connect(self.slot_updateMenuProjectList)
  697. self.ui.act_app_add_new.triggered.connect(self.slot_app_add_new)
  698. self.ui.act_app_run_custom.triggered.connect(self.slot_app_run_custom)
  699. self.ui.treeWidget.itemSelectionChanged.connect(self.slot_checkCurrentRoom)
  700. #self.ui.treeWidget.itemPressed.connect(self.slot_checkCurrentRoom)
  701. self.ui.treeWidget.itemDoubleClicked.connect(self.slot_doubleClickedAppList)
  702. self.ui.treeWidget.customContextMenuRequested.connect(self.slot_showAppListCustomMenu)
  703. self.ui.miniCanvasPreview.miniCanvasMoved.connect(self.slot_miniCanvasMoved)
  704. self.ui.graphicsView.horizontalScrollBar().valueChanged.connect(self.slot_horizontalScrollBarChanged)
  705. self.ui.graphicsView.verticalScrollBar().valueChanged.connect(self.slot_verticalScrollBarChanged)
  706. self.scene.sceneGroupMoved.connect(self.slot_canvasItemMoved)
  707. self.scene.scaleChanged.connect(self.slot_canvasScaleChanged)
  708. self.ui.act_settings_configure.triggered.connect(self.slot_configureClaudia)
  709. self.ui.act_help_about.triggered.connect(self.slot_aboutClaudia)
  710. self.ui.act_help_about_qt.triggered.connect(app.aboutQt)
  711. # org.freedesktop.DBus
  712. self.DBusCrashCallback.connect(self.slot_DBusCrashCallback)
  713. # org.jackaudio.JackControl
  714. self.DBusServerStartedCallback.connect(self.slot_DBusServerStartedCallback)
  715. self.DBusServerStoppedCallback.connect(self.slot_DBusServerStoppedCallback)
  716. # org.jackaudio.JackPatchbay
  717. self.DBusClientAppearedCallback.connect(self.slot_DBusClientAppearedCallback)
  718. self.DBusClientDisappearedCallback.connect(self.slot_DBusClientDisappearedCallback)
  719. self.DBusClientRenamedCallback.connect(self.slot_DBusClientRenamedCallback)
  720. self.DBusPortAppearedCallback.connect(self.slot_DBusPortAppearedCallback)
  721. self.DBusPortDisppearedCallback.connect(self.slot_DBusPortDisppearedCallback)
  722. self.DBusPortRenamedCallback.connect(self.slot_DBusPortRenamedCallback)
  723. self.DBusPortsConnectedCallback.connect(self.slot_DBusPortsConnectedCallback)
  724. self.DBusPortsDisconnectedCallback.connect(self.slot_DBusPortsDisconnectedCallback)
  725. # org.ladish.Control
  726. self.DBusStudioAppearedCallback.connect(self.slot_DBusStudioAppearedCallback)
  727. self.DBusStudioDisappearedCallback.connect(self.slot_DBusStudioDisappearedCallback)
  728. self.DBusQueueExecutionHaltedCallback.connect(self.slot_DBusQueueExecutionHaltedCallback)
  729. self.DBusCleanExitCallback.connect(self.slot_DBusCleanExitCallback)
  730. # org.ladish.Studio
  731. self.DBusStudioStartedCallback.connect(self.slot_DBusStudioStartedCallback)
  732. self.DBusStudioStoppedCallback.connect(self.slot_DBusStudioStoppedCallback)
  733. self.DBusStudioRenamedCallback.connect(self.slot_DBusStudioRenamedCallback)
  734. self.DBusStudioCrashedCallback.connect(self.slot_DBusStudioCrashedCallback)
  735. self.DBusRoomAppearedCallback.connect(self.slot_DBusRoomAppearedCallback)
  736. self.DBusRoomDisappearedCallback.connect(self.slot_DBusRoomDisappearedCallback)
  737. #self.DBusRoomChangedCallback.connect(self.slot_DBusRoomChangedCallback)
  738. # org.ladish.Room
  739. self.DBusProjectPropertiesChanged.connect(self.slot_DBusProjectPropertiesChanged)
  740. # org.ladish.AppSupervisor
  741. self.DBusAppAdded2Callback.connect(self.slot_DBusAppAdded2Callback)
  742. self.DBusAppRemovedCallback.connect(self.slot_DBusAppRemovedCallback)
  743. self.DBusAppStateChanged2Callback.connect(self.slot_DBusAppStateChanged2Callback)
  744. # JACK
  745. self.BufferSizeCallback.connect(self.slot_JackBufferSizeCallback)
  746. self.SampleRateCallback.connect(self.slot_JackSampleRateCallback)
  747. self.ShutdownCallback.connect(self.slot_JackShutdownCallback)
  748. # -------------------------------------------------------------
  749. # Set-up DBus
  750. gDBus.bus.add_signal_receiver(self.DBusSignalReceiver, destination_keyword="dest", path_keyword="path",
  751. member_keyword="member", interface_keyword="interface", sender_keyword="sender")
  752. # -------------------------------------------------------------
  753. def canvasCallback(self, action, value1, value2, value_str):
  754. if action == patchcanvas.ACTION_GROUP_INFO:
  755. pass
  756. elif action == patchcanvas.ACTION_GROUP_RENAME:
  757. group_id = value1
  758. group_name = value_str
  759. gDBus.ladish_manager.RenameClient(group_id, group_name)
  760. elif action == patchcanvas.ACTION_GROUP_SPLIT:
  761. group_id = value1
  762. gDBus.ladish_graph.Set(GRAPH_DICT_OBJECT_TYPE_CLIENT, group_id, URI_CANVAS_SPLIT, "true")
  763. patchcanvas.splitGroup(group_id)
  764. self.ui.miniCanvasPreview.update()
  765. elif action == patchcanvas.ACTION_GROUP_JOIN:
  766. group_id = value1
  767. gDBus.ladish_graph.Set(GRAPH_DICT_OBJECT_TYPE_CLIENT, group_id, URI_CANVAS_SPLIT, "false")
  768. patchcanvas.joinGroup(group_id)
  769. self.ui.miniCanvasPreview.update()
  770. elif action == patchcanvas.ACTION_PORT_INFO:
  771. this_port_id = value1
  772. breakNow = False
  773. port_id = 0
  774. port_flags = 0
  775. port_name = ""
  776. port_type_jack = 0
  777. version, groups, conns = gDBus.patchbay.GetGraph(0)
  778. for group in groups:
  779. group_id, group_name, ports = group
  780. for port in ports:
  781. port_id, port_name, port_flags, port_type_jack = port
  782. if this_port_id == port_id:
  783. breakNow = True
  784. break
  785. if breakNow:
  786. break
  787. else:
  788. return
  789. flags = []
  790. if port_flags & JACKDBUS_PORT_FLAG_INPUT:
  791. flags.append(self.tr("Input"))
  792. if port_flags & JACKDBUS_PORT_FLAG_OUTPUT:
  793. flags.append(self.tr("Output"))
  794. if port_flags & JACKDBUS_PORT_FLAG_PHYSICAL:
  795. flags.append(self.tr("Physical"))
  796. if port_flags & JACKDBUS_PORT_FLAG_CAN_MONITOR:
  797. flags.append(self.tr("Can Monitor"))
  798. if port_flags & JACKDBUS_PORT_FLAG_TERMINAL:
  799. flags.append(self.tr("Terminal"))
  800. flags_text = ""
  801. for flag in flags:
  802. if flags_text:
  803. flags_text += " | "
  804. flags_text += flag
  805. if port_type_jack == JACKDBUS_PORT_TYPE_AUDIO:
  806. type_text = self.tr("Audio")
  807. elif port_type_jack == JACKDBUS_PORT_TYPE_MIDI:
  808. type_text = self.tr("MIDI")
  809. else:
  810. type_text = self.tr("Unknown")
  811. port_full_name = "%s:%s" % (group_name, port_name)
  812. info = self.tr(""
  813. "<table>"
  814. "<tr><td align='right'><b>Group ID:</b></td><td>&nbsp;%i</td></tr>"
  815. "<tr><td align='right'><b>Group Name:</b></td><td>&nbsp;%s</td></tr>"
  816. "<tr><td align='right'><b>Port ID:</b></td><td>&nbsp;%i</i></td></tr>"
  817. "<tr><td align='right'><b>Port Name:</b></td><td>&nbsp;%s</td></tr>"
  818. "<tr><td align='right'><b>Full Port Name:</b></td><td>&nbsp;%s</td></tr>"
  819. "<tr><td colspan='2'>&nbsp;</td></tr>"
  820. "<tr><td align='right'><b>Port Flags:</b></td><td>&nbsp;%s</td></tr>"
  821. "<tr><td align='right'><b>Port Type:</b></td><td>&nbsp;%s</td></tr>"
  822. "</table>"
  823. % (group_id, group_name, port_id, port_name, port_full_name, flags_text, type_text))
  824. QMessageBox.information(self, self.tr("Port Information"), info)
  825. elif action == patchcanvas.ACTION_PORT_RENAME:
  826. port_id = value1
  827. port_name = value_str
  828. gDBus.ladish_manager.RenamePort(port_id, port_name)
  829. elif action == patchcanvas.ACTION_PORTS_CONNECT:
  830. port_a = value1
  831. port_b = value2
  832. gDBus.patchbay.ConnectPortsByID(port_a, port_b)
  833. elif action == patchcanvas.ACTION_PORTS_DISCONNECT:
  834. connection_id = value1
  835. gDBus.patchbay.DisconnectPortsByConnectionID(connection_id)
  836. def init_jack(self):
  837. self.fXruns = -1
  838. self.fNextSampleRate = 0.0
  839. self.fLastBPM = None
  840. self.fLastTransportState = None
  841. bufferSize = int(jacklib.get_buffer_size(gJack.client))
  842. sampleRate = int(jacklib.get_sample_rate(gJack.client))
  843. realtime = bool(int(jacklib.is_realtime(gJack.client)))
  844. self.ui_setBufferSize(bufferSize)
  845. self.ui_setSampleRate(sampleRate)
  846. self.ui_setRealTime(realtime)
  847. self.refreshDSPLoad()
  848. self.refreshTransport()
  849. self.refreshXruns()
  850. self.init_callbacks()
  851. jacklib.activate(gJack.client)
  852. def init_callbacks(self):
  853. jacklib.set_buffer_size_callback(gJack.client, self.JackBufferSizeCallback, None)
  854. jacklib.set_sample_rate_callback(gJack.client, self.JackSampleRateCallback, None)
  855. jacklib.on_shutdown(gJack.client, self.JackShutdownCallback, None)
  856. def init_studio(self):
  857. self.ui.treeWidget.clear()
  858. studio_item = QTreeWidgetItem(ITEM_TYPE_STUDIO)
  859. studio_item.setText(0, str(gDBus.ladish_studio.GetName()))
  860. self.ui.treeWidget.insertTopLevelItem(0, studio_item)
  861. self.ui.treeWidget.setCurrentItem(studio_item)
  862. self.m_lastItemType = ITEM_TYPE_STUDIO
  863. self.m_lastRoomPath = None
  864. self.init_apps()
  865. def init_apps(self):
  866. studio_iface = dbus.Interface(gDBus.ladish_studio, 'org.ladish.AppSupervisor')
  867. studio_item = self.ui.treeWidget.topLevelItem(0)
  868. graph_version, app_list = studio_iface.GetAll2()
  869. for app in app_list:
  870. number, name, active, terminal, level = app
  871. prop_obj = [None, None, None, None, None]
  872. prop_obj[iItemPropNumber] = int(number)
  873. prop_obj[iItemPropName] = str(name)
  874. prop_obj[iItemPropActive] = bool(active)
  875. prop_obj[iItemPropTerminal] = bool(terminal)
  876. prop_obj[iItemPropLevel] = str(level)
  877. text = "["
  878. if level.isdigit():
  879. text += "L%s" % level
  880. elif level == "jacksession":
  881. text += "JS"
  882. else:
  883. text += level.upper()
  884. text += "] "
  885. if not active:
  886. text += "(inactive) "
  887. text += name
  888. item = QTreeWidgetItem(ITEM_TYPE_STUDIO_APP)
  889. item.properties = prop_obj
  890. item.setText(0, text)
  891. studio_item.addChild(item)
  892. room_list = gDBus.ladish_studio.GetRoomList()
  893. for room in room_list:
  894. room_path, room_dict = room
  895. ladish_room = gDBus.bus.get_object("org.ladish", room_path)
  896. room_name = ladish_room.GetName()
  897. room_app_iface = dbus.Interface(ladish_room, 'org.ladish.AppSupervisor')
  898. room_item = self.room_add(room_path, room_name)
  899. graph_version, app_list = room_app_iface.GetAll2()
  900. for app in app_list:
  901. number, name, active, terminal, level = app
  902. prop_obj = [None, None, None, None, None]
  903. prop_obj[iItemPropNumber] = int(number)
  904. prop_obj[iItemPropName] = str(name)
  905. prop_obj[iItemPropActive] = bool(active)
  906. prop_obj[iItemPropTerminal] = bool(terminal)
  907. prop_obj[iItemPropLevel] = str(level)
  908. text = "["
  909. if level.isdigit():
  910. text += "L%s" % level
  911. elif level == "jacksession":
  912. text += "JS"
  913. else:
  914. text += level.upper()
  915. text += "] "
  916. if not active:
  917. text += "(inactive) "
  918. text += name
  919. item = QTreeWidgetItem(ITEM_TYPE_ROOM_APP)
  920. item.properties = prop_obj
  921. item.setText(0, text)
  922. room_item.addChild(item)
  923. self.ui.treeWidget.expandAll()
  924. def initPorts(self):
  925. if not (gJack.client and gDBus.patchbay):
  926. return
  927. version, groups, conns = gDBus.patchbay.GetGraph(0)
  928. # Graph Ports
  929. for group in groups:
  930. group_id, group_name, ports = group
  931. self.canvas_add_group(int(group_id), str(group_name))
  932. for port in ports:
  933. port_id, port_name, port_flags, port_type_jack = port
  934. if port_flags & JACKDBUS_PORT_FLAG_INPUT:
  935. port_mode = patchcanvas.PORT_MODE_INPUT
  936. elif port_flags & JACKDBUS_PORT_FLAG_OUTPUT:
  937. port_mode = patchcanvas.PORT_MODE_OUTPUT
  938. else:
  939. port_mode = patchcanvas.PORT_MODE_NULL
  940. if port_type_jack == JACKDBUS_PORT_TYPE_AUDIO:
  941. port_type = patchcanvas.PORT_TYPE_AUDIO_JACK
  942. elif port_type_jack == JACKDBUS_PORT_TYPE_MIDI:
  943. if gDBus.ladish_graph.Get(GRAPH_DICT_OBJECT_TYPE_PORT, port_id, URI_A2J_PORT) == "yes":
  944. port_type = patchcanvas.PORT_TYPE_MIDI_A2J
  945. else:
  946. port_type = patchcanvas.PORT_TYPE_MIDI_JACK
  947. else:
  948. port_type = patchcanvas.PORT_TYPE_NULL
  949. self.canvas_add_port(int(group_id), int(port_id), str(port_name), port_mode, port_type)
  950. # Graph Connections
  951. for conn in conns:
  952. source_group_id, source_group_name, source_port_id, source_port_name, target_group_id, target_group_name, target_port_id, target_port_name, conn_id = conn
  953. self.canvas_connect_ports(int(conn_id), int(source_port_id), int(target_port_id))
  954. QTimer.singleShot(1000 if (self.fSavedSettings['Canvas/EyeCandy']) else 0, self.ui.miniCanvasPreview.update)
  955. def room_add(self, room_path, room_name):
  956. room_index = int(room_path.replace("/org/ladish/Room", ""))
  957. room_object = gDBus.bus.get_object("org.ladish", room_path)
  958. room_project_properties = room_object.GetProjectProperties()
  959. # Remove old unused item if needed
  960. iItem = self.ui.treeWidget.topLevelItem(room_index)
  961. if iItem and not iItem.isVisible():
  962. self.ui.treeWidget.takeTopLevelItem(room_index)
  963. # Insert padding of items if needed
  964. for i in range(room_index):
  965. if not self.ui.treeWidget.topLevelItem(i):
  966. fake_item = QTreeWidgetItem(ITEM_TYPE_NULL)
  967. self.ui.treeWidget.insertTopLevelItem(i, fake_item)
  968. fake_item.setHidden(True)
  969. graph_version, project_properties = room_project_properties
  970. if len(project_properties) > 0:
  971. item_string = " (%s)" % project_properties['name']
  972. else:
  973. item_string = ""
  974. prop_obj = [None, None]
  975. prop_obj[iItemPropRoomPath] = room_path
  976. prop_obj[iItemPropRoomName] = room_name
  977. item = QTreeWidgetItem(ITEM_TYPE_ROOM)
  978. item.properties = prop_obj
  979. item.setText(0, "%s%s" % (room_name, item_string))
  980. self.ui.treeWidget.insertTopLevelItem(room_index, item)
  981. self.ui.treeWidget.expandItem(item)
  982. return item
  983. def canvas_add_group(self, groupId, groupName):
  984. # TODO - request ladish client type
  985. #if (False):
  986. #icon = patchcanvas.ICON_HARDWARE
  987. #split = patchcanvas.SPLIT_NO
  988. #elif (False):
  989. #icon = patchcanvas.ICON_LADISH_ROOM
  990. #split = patchcanvas.SPLIT_NO
  991. #else:
  992. splitTry = gDBus.ladish_graph.Get(GRAPH_DICT_OBJECT_TYPE_CLIENT, groupId, URI_CANVAS_SPLIT)
  993. if splitTry == "true":
  994. groupSplit = patchcanvas.SPLIT_YES
  995. elif splitTry == "false":
  996. groupSplit = patchcanvas.SPLIT_NO
  997. else:
  998. groupSplit = patchcanvas.SPLIT_UNDEF
  999. groupIcon = patchcanvas.ICON_APPLICATION
  1000. if gJack.client:
  1001. ret, data, dataSize = jacklib.custom_get_data(gJack.client, groupName, URI_CANVAS_ICON)
  1002. if ret == 0:
  1003. iconName = voidptr2str(data)
  1004. jacklib.free(data)
  1005. if iconName == "hardware":
  1006. groupIcon = patchcanvas.ICON_HARDWARE
  1007. if groupSplit == patchcanvas.SPLIT_UNDEF:
  1008. groupSplit = patchcanvas.SPLIT_YES
  1009. #elif iconName =="carla":
  1010. #groupIcon = patchcanvas.ICON_CARLA
  1011. elif iconName =="distrho":
  1012. groupIcon = patchcanvas.ICON_DISTRHO
  1013. elif iconName =="file":
  1014. groupIcon = patchcanvas.ICON_FILE
  1015. elif iconName =="plugin":
  1016. groupIcon = patchcanvas.ICON_PLUGIN
  1017. patchcanvas.addGroup(groupId, groupName, groupSplit, groupIcon)
  1018. x = gDBus.ladish_graph.Get(GRAPH_DICT_OBJECT_TYPE_CLIENT, groupId, URI_CANVAS_X)
  1019. y = gDBus.ladish_graph.Get(GRAPH_DICT_OBJECT_TYPE_CLIENT, groupId, URI_CANVAS_Y)
  1020. x2 = gDBus.ladish_graph.Get(GRAPH_DICT_OBJECT_TYPE_CLIENT, groupId, URI_CANVAS_X_SPLIT)
  1021. y2 = gDBus.ladish_graph.Get(GRAPH_DICT_OBJECT_TYPE_CLIENT, groupId, URI_CANVAS_Y_SPLIT)
  1022. if x != None and y != None:
  1023. if x2 is None: x2 = "%f" % (float(x) + 50)
  1024. if y2 is None: y2 = "%f" % (float(y) + 50)
  1025. patchcanvas.setGroupPosFull(groupId, float(x), float(y), float(x2), float(y2))
  1026. QTimer.singleShot(0, self.ui.miniCanvasPreview.update)
  1027. def canvas_remove_group(self, group_id):
  1028. patchcanvas.removeGroup(group_id)
  1029. QTimer.singleShot(0, self.ui.miniCanvasPreview.update)
  1030. def canvas_rename_group(self, group_id, new_group_name):
  1031. patchcanvas.renameGroup(group_id, new_group_name)
  1032. QTimer.singleShot(0, self.ui.miniCanvasPreview.update)
  1033. def canvas_add_port(self, group_id, port_id, port_name, port_mode, port_type):
  1034. patchcanvas.addPort(group_id, port_id, port_name, port_mode, port_type)
  1035. QTimer.singleShot(0, self.ui.miniCanvasPreview.update)
  1036. def canvas_remove_port(self, port_id):
  1037. patchcanvas.removePort(port_id)
  1038. QTimer.singleShot(0, self.ui.miniCanvasPreview.update)
  1039. def canvas_rename_port(self, port_id, new_port_name):
  1040. patchcanvas.renamePort(port_id, new_port_name)
  1041. QTimer.singleShot(0, self.ui.miniCanvasPreview.update)
  1042. def canvas_connect_ports(self, connection_id, port_a, port_b):
  1043. patchcanvas.connectPorts(connection_id, port_a, port_b)
  1044. QTimer.singleShot(0, self.ui.miniCanvasPreview.update)
  1045. def canvas_disconnect_ports(self, connection_id):
  1046. patchcanvas.disconnectPorts(connection_id)
  1047. QTimer.singleShot(0, self.ui.miniCanvasPreview.update)
  1048. def jackStarted(self):
  1049. if jacksettings.needsInit():
  1050. self.DBusReconnect()
  1051. if not gJack.client:
  1052. gJack.client = jacklib.client_open("claudia", jacklib.JackNoStartServer, None)
  1053. if not gJack.client:
  1054. return self.jackStopped()
  1055. canRender = render.canRender()
  1056. self.ui.act_jack_render.setEnabled(canRender)
  1057. self.ui.b_jack_render.setEnabled(canRender)
  1058. self.menuJackTransport(True)
  1059. self.menuA2JBridge(False)
  1060. self.ui.cb_buffer_size.setEnabled(True)
  1061. self.ui.cb_sample_rate.setEnabled(True) # jacksettings.getSampleRate() != -1
  1062. if self.systray:
  1063. self.systray.setActionEnabled("tools_render", canRender)
  1064. self.ui.pb_dsp_load.setMaximum(100)
  1065. self.ui.pb_dsp_load.setValue(0)
  1066. self.ui.pb_dsp_load.update()
  1067. self.init_jack()
  1068. self.m_crashedJACK = False
  1069. def jackStopped(self):
  1070. #self.DBusReconnect()
  1071. # client already closed
  1072. gJack.client = None
  1073. if self.fNextSampleRate:
  1074. self.jack_setSampleRate(self.fNextSampleRate)
  1075. bufferSize = jacksettings.getBufferSize()
  1076. sampleRate = jacksettings.getSampleRate()
  1077. bufferSizeTest = bool(bufferSize != -1)
  1078. sampleRateTest = bool(sampleRate != -1)
  1079. if bufferSizeTest:
  1080. self.ui_setBufferSize(bufferSize)
  1081. if sampleRateTest:
  1082. self.ui_setSampleRate(sampleRate)
  1083. self.ui_setRealTime(jacksettings.isRealtime())
  1084. self.ui_setXruns(-1)
  1085. self.ui.cb_buffer_size.setEnabled(bufferSizeTest)
  1086. self.ui.cb_sample_rate.setEnabled(sampleRateTest)
  1087. self.ui.act_jack_render.setEnabled(False)
  1088. self.ui.b_jack_render.setEnabled(False)
  1089. self.menuJackTransport(False)
  1090. self.menuA2JBridge(False)
  1091. if self.systray:
  1092. self.systray.setActionEnabled("tools_render", False)
  1093. if self.fCurTransportView == TRANSPORT_VIEW_HMS:
  1094. self.ui.label_time.setText("00:00:00")
  1095. elif self.fCurTransportView == TRANSPORT_VIEW_BBT:
  1096. self.ui.label_time.setText("000|0|0000")
  1097. elif self.fCurTransportView == TRANSPORT_VIEW_FRAMES:
  1098. self.ui.label_time.setText("000'000'000")
  1099. self.ui.pb_dsp_load.setValue(0)
  1100. self.ui.pb_dsp_load.setMaximum(0)
  1101. self.ui.pb_dsp_load.update()
  1102. def studioStarted(self):
  1103. self.ui.act_studio_start.setEnabled(False)
  1104. self.ui.act_studio_stop.setEnabled(True)
  1105. self.ui.act_studio_save.setEnabled(True)
  1106. self.ui.act_studio_save_as.setEnabled(True)
  1107. self.ui.b_studio_save.setEnabled(True)
  1108. self.ui.b_studio_save_as.setEnabled(True)
  1109. self.ui.b_studio_start.setEnabled(False)
  1110. self.ui.b_studio_stop.setEnabled(True)
  1111. if self.systray:
  1112. self.systray.setActionEnabled("studio_start", False)
  1113. self.systray.setActionEnabled("studio_stop", True)
  1114. self.systray.setActionEnabled("studio_save", True)
  1115. self.systray.setActionEnabled("studio_save_as", True)
  1116. def studioStopped(self):
  1117. self.ui.act_studio_start.setEnabled(True)
  1118. self.ui.act_studio_stop.setEnabled(False)
  1119. self.ui.act_studio_save.setEnabled(False)
  1120. self.ui.act_studio_save_as.setEnabled(False)
  1121. self.ui.b_studio_save.setEnabled(False)
  1122. self.ui.b_studio_save_as.setEnabled(False)
  1123. self.ui.b_studio_start.setEnabled(True)
  1124. self.ui.b_studio_stop.setEnabled(False)
  1125. if self.systray:
  1126. self.systray.setActionEnabled("studio_start", True)
  1127. self.systray.setActionEnabled("studio_stop", False)
  1128. self.systray.setActionEnabled("studio_save", False)
  1129. self.systray.setActionEnabled("studio_save_as", False)
  1130. def studioLoaded(self):
  1131. gDBus.ladish_studio = gDBus.bus.get_object("org.ladish", "/org/ladish/Studio")
  1132. gDBus.ladish_graph = dbus.Interface(gDBus.ladish_studio, 'org.ladish.GraphDict')
  1133. gDBus.ladish_manager = dbus.Interface(gDBus.ladish_studio, 'org.ladish.GraphManager')
  1134. gDBus.ladish_app_iface = dbus.Interface(gDBus.ladish_studio, 'org.ladish.AppSupervisor')
  1135. gDBus.patchbay = dbus.Interface(gDBus.ladish_studio, 'org.jackaudio.JackPatchbay')
  1136. self.ui.label_first_time.setVisible(False)
  1137. self.ui.graphicsView.setVisible(True)
  1138. self.ui.miniCanvasPreview.setVisible(True)
  1139. #if (self.ui.miniCanvasPreview.is_initiated):
  1140. #self.checkMiniCanvasSize()
  1141. self.ui.menu_Room.setEnabled(True)
  1142. self.ui.menu_Project.setEnabled(False)
  1143. self.ui.menu_Application.setEnabled(True)
  1144. self.ui.group_project.setEnabled(False)
  1145. self.ui.act_studio_rename.setEnabled(True)
  1146. self.ui.act_studio_unload.setEnabled(True)
  1147. if self.systray:
  1148. self.systray.setActionEnabled("studio_rename", True)
  1149. self.systray.setActionEnabled("studio_unload", True)
  1150. self.init_studio()
  1151. self.m_crashedLADISH = False
  1152. def studioUnloaded(self):
  1153. gDBus.ladish_studio = None
  1154. gDBus.ladish_graph = None
  1155. gDBus.ladish_manager = None
  1156. gDBus.ladish_app_iface = None
  1157. gDBus.patchbay = None
  1158. self.m_lastItemType = None
  1159. self.m_lastRoomPath = None
  1160. self.ui.label_first_time.setVisible(True)
  1161. self.ui.graphicsView.setVisible(False)
  1162. self.ui.miniCanvasPreview.setVisible(False)
  1163. self.ui.menu_Room.setEnabled(False)
  1164. self.ui.menu_Project.setEnabled(False)
  1165. self.ui.menu_Application.setEnabled(False)
  1166. self.ui.group_project.setEnabled(False)
  1167. self.ui.act_studio_start.setEnabled(False)
  1168. self.ui.act_studio_stop.setEnabled(False)
  1169. self.ui.act_studio_rename.setEnabled(False)
  1170. self.ui.act_studio_save.setEnabled(False)
  1171. self.ui.act_studio_save_as.setEnabled(False)
  1172. self.ui.act_studio_unload.setEnabled(False)
  1173. self.ui.b_studio_save.setEnabled(False)
  1174. self.ui.b_studio_save_as.setEnabled(False)
  1175. self.ui.b_studio_start.setEnabled(False)
  1176. self.ui.b_studio_stop.setEnabled(False)
  1177. if self.systray:
  1178. self.systray.setActionEnabled("studio_start", False)
  1179. self.systray.setActionEnabled("studio_stop", False)
  1180. self.systray.setActionEnabled("studio_rename", False)
  1181. self.systray.setActionEnabled("studio_save", False)
  1182. self.systray.setActionEnabled("studio_save_as", False)
  1183. self.systray.setActionEnabled("studio_unload", False)
  1184. self.ui.treeWidget.clear()
  1185. patchcanvas.clear()
  1186. def a2jStarted(self):
  1187. self.menuA2JBridge(True)
  1188. def a2jStopped(self):
  1189. self.menuA2JBridge(False)
  1190. def menuJackTransport(self, enabled):
  1191. self.ui.act_transport_play.setEnabled(enabled)
  1192. self.ui.act_transport_stop.setEnabled(enabled)
  1193. self.ui.act_transport_backwards.setEnabled(enabled)
  1194. self.ui.act_transport_forwards.setEnabled(enabled)
  1195. self.ui.menu_Transport.setEnabled(enabled)
  1196. self.ui.group_transport.setEnabled(enabled)
  1197. def menuA2JBridge(self, started):
  1198. if not gDBus.jack.IsStarted():
  1199. self.ui.act_tools_a2j_start.setEnabled(False)
  1200. self.ui.act_tools_a2j_stop.setEnabled(False)
  1201. self.ui.act_tools_a2j_export_hw.setEnabled(bool(gDBus.a2j) and not gDBus.a2j.is_started())
  1202. else:
  1203. self.ui.act_tools_a2j_start.setEnabled(not started)
  1204. self.ui.act_tools_a2j_stop.setEnabled(started)
  1205. self.ui.act_tools_a2j_export_hw.setEnabled(not started)
  1206. def DBusSignalReceiver(self, *args, **kwds):
  1207. if kwds['interface'] == "org.freedesktop.DBus" and kwds['path'] == "/org/freedesktop/DBus" and kwds['member'] == "NameOwnerChanged":
  1208. appInterface, appId, newId = args
  1209. #print("appInterface crashed", appInterface)
  1210. if not newId:
  1211. # Something crashed
  1212. if appInterface == "org.gna.home.a2jmidid":
  1213. QTimer.singleShot(0, self.slot_handleCrash_a2j)
  1214. elif appInterface in ("org.jackaudio.service", "org.ladish"):
  1215. # Prevent any more dbus calls
  1216. gDBus.jack = None
  1217. gJack.client = None
  1218. jacksettings.initBus(None)
  1219. self.DBusCrashCallback.emit(appInterface)
  1220. elif kwds['interface'] == "org.jackaudio.JackControl":
  1221. if DEBUG: print("DBus signal @org.jackaudio.JackControl,", kwds['member'])
  1222. if kwds['member'] == "ServerStarted":
  1223. self.DBusServerStartedCallback.emit()
  1224. elif kwds['member'] == "ServerStopped":
  1225. self.DBusServerStoppedCallback.emit()
  1226. elif kwds['interface'] == "org.jackaudio.JackPatchbay":
  1227. if gDBus.patchbay and kwds['path'] == gDBus.patchbay.object_path:
  1228. if DEBUG: print("DBus signal @org.jackaudio.JackPatchbay,", kwds['member'])
  1229. if kwds['member'] == "ClientAppeared":
  1230. self.DBusClientAppearedCallback.emit(args[iJackClientId], args[iJackClientName])
  1231. elif kwds['member'] == "ClientDisappeared":
  1232. self.DBusClientDisappearedCallback.emit(args[iJackClientId])
  1233. elif kwds['member'] == "ClientRenamed":
  1234. self.DBusClientRenamedCallback.emit(args[iRenamedId], args[iRenamedNewName])
  1235. elif kwds['member'] == "PortAppeared":
  1236. self.DBusPortAppearedCallback.emit(args[iJackClientId], args[iJackPortId], args[iJackPortName], args[iJackPortFlags], args[iJackPortType])
  1237. elif kwds['member'] == "PortDisappeared":
  1238. self.DBusPortDisppearedCallback.emit(args[iJackPortId])
  1239. elif kwds['member'] == "PortRenamed":
  1240. self.DBusPortRenamedCallback.emit(args[iJackPortId], args[iJackPortNewName])
  1241. elif kwds['member'] == "PortsConnected":
  1242. self.DBusPortsConnectedCallback.emit(args[iJackConnId], args[iSourcePortId], args[iTargetPortId])
  1243. elif kwds['member'] == "PortsDisconnected":
  1244. self.DBusPortsDisconnectedCallback.emit(args[iJackConnId])
  1245. elif kwds['interface'] == "org.ladish.Control":
  1246. if DEBUG: print("DBus signal @org.ladish.Control,", kwds['member'])
  1247. if kwds['member'] == "StudioAppeared":
  1248. self.DBusStudioAppearedCallback.emit()
  1249. elif kwds['member'] == "StudioDisappeared":
  1250. self.DBusStudioDisappearedCallback.emit()
  1251. elif kwds['member'] == "QueueExecutionHalted":
  1252. self.DBusQueueExecutionHaltedCallback.emit()
  1253. elif kwds['member'] == "CleanExit":
  1254. self.DBusCleanExitCallback.emit()
  1255. elif kwds['interface'] == "org.ladish.Studio":
  1256. if DEBUG: print("DBus signal @org.ladish.Studio,", kwds['member'])
  1257. if kwds['member'] == "StudioStarted":
  1258. self.DBusStudioStartedCallback.emit()
  1259. elif kwds['member'] == "StudioStopped":
  1260. self.DBusStudioStoppedCallback.emit()
  1261. elif kwds['member'] == "StudioRenamed":
  1262. self.DBusStudioRenamedCallback.emit(args[iStudioRenamedName])
  1263. elif kwds['member'] == "StudioCrashed":
  1264. self.DBusStudioCrashedCallback.emit()
  1265. elif kwds['member'] == "RoomAppeared":
  1266. self.DBusRoomAppearedCallback.emit(args[iRoomAppearedPath], args[iRoomAppearedDict]['name'])
  1267. elif kwds['member'] == "RoomDisappeared":
  1268. self.DBusRoomDisappearedCallback.emit(args[iRoomAppearedPath])
  1269. #elif kwds['member'] == "RoomChanged":
  1270. #self.DBusRoomChangedCallback.emit()
  1271. elif kwds['interface'] == "org.ladish.Room":
  1272. if DEBUG: print("DBus signal @org.ladish.Room,", kwds['member'])
  1273. if kwds['member'] == "ProjectPropertiesChanged":
  1274. if "name" in args[iProjChangedDict].keys():
  1275. self.DBusProjectPropertiesChanged.emit(kwds['path'], args[iProjChangedDict]['name'])
  1276. else:
  1277. self.DBusProjectPropertiesChanged.emit(kwds['path'], "")
  1278. elif kwds['interface'] == "org.ladish.AppSupervisor":
  1279. if DEBUG: print("DBus signal @org.ladish.AppSupervisor,", kwds['member'])
  1280. if kwds['member'] == "AppAdded2":
  1281. self.DBusAppAdded2Callback.emit(kwds['path'], args[iAppChangedNumber], args[iAppChangedName], args[iAppChangedActive], args[iAppChangedTerminal], args[iAppChangedLevel])
  1282. elif kwds['member'] == "AppRemoved":
  1283. self.DBusAppRemovedCallback.emit(kwds['path'], args[iAppChangedNumber])
  1284. elif kwds['member'] == "AppStateChanged2":
  1285. self.DBusAppStateChanged2Callback.emit(kwds['path'], args[iAppChangedNumber], args[iAppChangedName], args[iAppChangedActive], args[iAppChangedTerminal], args[iAppChangedLevel])
  1286. elif kwds['interface'] == "org.gna.home.a2jmidid.control":
  1287. if kwds['member'] == "bridge_started":
  1288. self.a2jStarted()
  1289. elif kwds['member'] == "bridge_stopped":
  1290. self.a2jStopped()
  1291. def DBusReconnect(self):
  1292. gDBus.jack = gDBus.bus.get_object("org.jackaudio.service", "/org/jackaudio/Controller")
  1293. gDBus.ladish_control = gDBus.bus.get_object("org.ladish", "/org/ladish/Control")
  1294. gDBus.ladish_studio = None
  1295. gDBus.ladish_room = None
  1296. gDBus.ladish_graph = None
  1297. gDBus.ladish_manager = None
  1298. gDBus.ladish_app_iface = None
  1299. gDBus.patchbay = None
  1300. try:
  1301. gDBus.ladish_app_daemon = gDBus.bus.get_object("org.ladish.appdb", "/")
  1302. except:
  1303. gDBus.ladish_app_daemon = None
  1304. try:
  1305. gDBus.a2j = dbus.Interface(gDBus.bus.get_object("org.gna.home.a2jmidid", "/"), "org.gna.home.a2jmidid.control")
  1306. except:
  1307. gDBus.a2j = None
  1308. jacksettings.initBus(gDBus.bus)
  1309. def refreshXruns(self):
  1310. if not gDBus.jack:
  1311. #if not self.m_crashedJACK:
  1312. #self.DBusReconnect()
  1313. return
  1314. xruns = int(gDBus.jack.GetXruns())
  1315. if self.fXruns != xruns:
  1316. self.ui_setXruns(xruns)
  1317. self.fXruns = xruns
  1318. def JackBufferSizeCallback(self, buffer_size, arg):
  1319. if DEBUG: print("JackBufferSizeCallback(%i)" % buffer_size)
  1320. self.BufferSizeCallback.emit(buffer_size)
  1321. return 0
  1322. def JackSampleRateCallback(self, sample_rate, arg):
  1323. if DEBUG: print("JackSampleRateCallback(%i)" % sample_rate)
  1324. self.SampleRateCallback.emit(sample_rate)
  1325. return 0
  1326. def JackShutdownCallback(self, arg):
  1327. if DEBUG: print("JackShutdownCallback")
  1328. self.ShutdownCallback.emit()
  1329. return 0
  1330. @pyqtSlot()
  1331. def slot_studio_new(self):
  1332. dialog = StudioNameW(self, StudioNameW.NEW)
  1333. if dialog.exec_():
  1334. gDBus.ladish_control.NewStudio(dialog.fRetStudioName)
  1335. @pyqtSlot()
  1336. def slot_studio_load_b(self):
  1337. dialog = StudioListW(self)
  1338. if dialog.exec_():
  1339. gDBus.ladish_control.LoadStudio(dialog.ret_studio_name)
  1340. @pyqtSlot()
  1341. def slot_studio_load_m(self):
  1342. studio_name = self.sender().property("data")
  1343. if studio_name:
  1344. gDBus.ladish_control.LoadStudio(studio_name)
  1345. @pyqtSlot()
  1346. def slot_studio_start(self):
  1347. gDBus.ladish_studio.Start()
  1348. @pyqtSlot()
  1349. def slot_studio_stop(self):
  1350. gDBus.ladish_studio.Stop()
  1351. @pyqtSlot()
  1352. def slot_studio_rename(self):
  1353. dialog = StudioNameW(self, StudioNameW.RENAME)
  1354. if dialog.exec_():
  1355. gDBus.ladish_studio.Rename(dialog.fRetStudioName)
  1356. @pyqtSlot()
  1357. def slot_studio_save(self):
  1358. gDBus.ladish_studio.Save()
  1359. @pyqtSlot()
  1360. def slot_studio_save_as(self):
  1361. dialog = StudioNameW(self, StudioNameW.SAVE_AS)
  1362. if dialog.exec_():
  1363. gDBus.ladish_studio.SaveAs(dialog.fRetStudioName)
  1364. @pyqtSlot()
  1365. def slot_studio_unload(self):
  1366. gDBus.ladish_studio.Unload()
  1367. @pyqtSlot()
  1368. def slot_studio_delete_m(self):
  1369. studio_name = self.sender().property("data")
  1370. if studio_name:
  1371. gDBus.ladish_control.DeleteStudio(studio_name)
  1372. @pyqtSlot()
  1373. def slot_room_create(self):
  1374. dialog = CreateRoomW(self)
  1375. if dialog.exec_():
  1376. gDBus.ladish_studio.CreateRoom(dialog.ret_room_name, dialog.ret_room_template)
  1377. @pyqtSlot()
  1378. def slot_room_delete_m(self):
  1379. room_name = self.sender().property("data")
  1380. if room_name:
  1381. gDBus.ladish_studio.DeleteRoom(room_name)
  1382. @pyqtSlot()
  1383. def slot_project_new(self):
  1384. dialog = ProjectNameW(self, ProjectNameW.NEW, self.fSavedSettings["Main/DefaultProjectFolder"])
  1385. if dialog.exec_():
  1386. # Check if a project is already loaded, if yes unload it first
  1387. project_graph_version, project_properties = gDBus.ladish_room.GetProjectProperties()
  1388. if len(project_properties) > 0:
  1389. gDBus.ladish_room.UnloadProject()
  1390. gDBus.ladish_room.SaveProject(dialog.ret_project_path, dialog.ret_project_name)
  1391. @pyqtSlot()
  1392. def slot_project_load(self):
  1393. project_path = QFileDialog.getExistingDirectory(self, self.tr("Open Project"), self.fSavedSettings["Main/DefaultProjectFolder"])
  1394. if project_path:
  1395. if os.path.exists(os.path.join(project_path, "ladish-project.xml")):
  1396. gDBus.ladish_room.LoadProject(project_path)
  1397. else:
  1398. QMessageBox.warning(self, self.tr("Warning"), self.tr("The selected folder does not contain a ladish project"))
  1399. @pyqtSlot()
  1400. def slot_project_load_m(self):
  1401. act_x_text = self.sender().property("data")
  1402. if act_x_text:
  1403. proj_path = "/" + act_x_text.rsplit("[/", 1)[-1].rsplit("]", 1)[0]
  1404. gDBus.ladish_room.LoadProject(proj_path)
  1405. @pyqtSlot()
  1406. def slot_project_save(self):
  1407. project_graph_version, project_properties = gDBus.ladish_room.GetProjectProperties()
  1408. if len(project_properties) > 0:
  1409. path = dbus.String(project_properties['dir'])
  1410. name = dbus.String(project_properties['name'])
  1411. gDBus.ladish_room.SaveProject(path, name)
  1412. else:
  1413. self.slot_project_new()
  1414. @pyqtSlot()
  1415. def slot_project_save_as(self):
  1416. project_graph_version, project_properties = gDBus.ladish_room.GetProjectProperties()
  1417. if len(project_properties) > 0:
  1418. path = str(project_properties['dir'])
  1419. name = str(project_properties['name'])
  1420. dialog = ProjectNameW(self, ProjectNameW.SAVE_AS, self.fSavedSettings["Main/DefaultProjectFolder"], path, name)
  1421. if dialog.exec_():
  1422. gDBus.ladish_room.SaveProject(dialog.ret_project_path, dialog.ret_project_name)
  1423. else:
  1424. self.slot_project_new()
  1425. @pyqtSlot()
  1426. def slot_project_unload(self):
  1427. gDBus.ladish_room.UnloadProject()
  1428. @pyqtSlot()
  1429. def slot_project_properties(self):
  1430. project_graph_version, project_properties = gDBus.ladish_room.GetProjectProperties()
  1431. path = str(project_properties['dir'])
  1432. name = str(project_properties['name'])
  1433. if "description" in project_properties.keys():
  1434. description = str(project_properties['description'])
  1435. else:
  1436. description = ""
  1437. if "notes" in project_properties.keys():
  1438. notes = str(project_properties['notes'])
  1439. else:
  1440. notes = ""
  1441. dialog = ProjectPropertiesW(self, name, description, notes)
  1442. if dialog.exec_():
  1443. gDBus.ladish_room.SetProjectDescription(dialog.ret_obj[iAppPropDescription])
  1444. gDBus.ladish_room.SetProjectNotes(dialog.ret_obj[iAppPropNotes])
  1445. if dialog.ret_obj[iAppPropSaveNow]:
  1446. gDBus.ladish_room.SaveProject(path, dialog.ret_obj[iAppPropName])
  1447. @pyqtSlot()
  1448. def slot_app_add_new(self):
  1449. proj_folder = ""
  1450. if self.m_lastItemType == ITEM_TYPE_STUDIO or self.m_lastItemType == ITEM_TYPE_STUDIO_APP:
  1451. proj_folder = self.fSavedSettings['Main/DefaultProjectFolder']
  1452. is_room = False
  1453. elif self.m_lastItemType == ITEM_TYPE_ROOM or self.m_lastItemType == ITEM_TYPE_ROOM_APP:
  1454. project_graph_version, project_properties = gDBus.ladish_room.GetProjectProperties()
  1455. if len(project_properties) > 0:
  1456. proj_folder = str(project_properties['dir'])
  1457. is_room = True
  1458. else:
  1459. proj_folder = self.fSavedSettings['Main/DefaultProjectFolder']
  1460. is_room = False
  1461. else:
  1462. print("Invalid m_last_item_type value")
  1463. return
  1464. dialog = ClaudiaLauncherW(self, gDBus.ladish_app_iface, proj_folder, is_room, self.fLastBPM, self.fSampleRate)
  1465. dialog.exec_()
  1466. @pyqtSlot()
  1467. def slot_app_run_custom(self):
  1468. dialog = RunCustomW(self, bool(self.m_lastItemType in (ITEM_TYPE_ROOM, ITEM_TYPE_ROOM_APP)))
  1469. if dialog.exec_() and dialog.ret_app_obj:
  1470. app_obj = dialog.ret_app_obj
  1471. gDBus.ladish_app_iface.RunCustom2(app_obj[iAppTerminal], app_obj[iAppCommand], app_obj[iAppName], app_obj[iAppLevel])
  1472. @pyqtSlot()
  1473. def slot_checkCurrentRoom(self):
  1474. item = self.ui.treeWidget.currentItem()
  1475. room_path = None
  1476. if not item:
  1477. return
  1478. if item.type() in (ITEM_TYPE_STUDIO, ITEM_TYPE_STUDIO_APP):
  1479. self.ui.menu_Project.setEnabled(False)
  1480. self.ui.group_project.setEnabled(False)
  1481. self.ui.menu_Application.setEnabled(True)
  1482. gDBus.ladish_room = None
  1483. gDBus.ladish_app_iface = dbus.Interface(gDBus.ladish_studio, "org.ladish.AppSupervisor")
  1484. ITEM_TYPE = ITEM_TYPE_STUDIO
  1485. elif item.type() in (ITEM_TYPE_ROOM, ITEM_TYPE_ROOM_APP):
  1486. self.ui.menu_Project.setEnabled(True)
  1487. self.ui.group_project.setEnabled(True)
  1488. if item.type() == ITEM_TYPE_ROOM:
  1489. room_path = item.properties[iItemPropRoomPath]
  1490. elif item.type() == ITEM_TYPE_ROOM_APP:
  1491. room_path = item.parent().properties[iItemPropRoomPath]
  1492. else:
  1493. return
  1494. gDBus.ladish_room = gDBus.bus.get_object("org.ladish", room_path)
  1495. gDBus.ladish_app_iface = dbus.Interface(gDBus.ladish_room, "org.ladish.AppSupervisor")
  1496. ITEM_TYPE = ITEM_TYPE_ROOM
  1497. project_graph_version, project_properties = gDBus.ladish_room.GetProjectProperties()
  1498. has_project = bool(len(project_properties) > 0)
  1499. self.ui.act_project_save.setEnabled(has_project)
  1500. self.ui.act_project_save_as.setEnabled(has_project)
  1501. self.ui.act_project_unload.setEnabled(has_project)
  1502. self.ui.act_project_properties.setEnabled(has_project)
  1503. self.ui.b_project_save.setEnabled(has_project)
  1504. self.ui.b_project_save_as.setEnabled(has_project)
  1505. self.ui.menu_Application.setEnabled(has_project)
  1506. else:
  1507. return
  1508. if ITEM_TYPE != self.m_lastItemType or room_path != self.m_lastRoomPath:
  1509. if ITEM_TYPE == ITEM_TYPE_STUDIO:
  1510. object_path = gDBus.ladish_studio
  1511. elif ITEM_TYPE == ITEM_TYPE_ROOM:
  1512. object_path = gDBus.ladish_room
  1513. else:
  1514. return
  1515. patchcanvas.clear()
  1516. gDBus.patchbay = dbus.Interface(object_path, 'org.jackaudio.JackPatchbay')
  1517. gDBus.ladish_graph = dbus.Interface(object_path, 'org.ladish.GraphDict')
  1518. gDBus.ladish_manager = dbus.Interface(object_path, 'org.ladish.GraphManager')
  1519. self.initPorts()
  1520. self.m_lastItemType = ITEM_TYPE
  1521. self.m_lastRoomPath = room_path
  1522. @pyqtSlot(QTreeWidgetItem, int)
  1523. def slot_doubleClickedAppList(self, item, row):
  1524. if item.type() in (ITEM_TYPE_STUDIO_APP, ITEM_TYPE_ROOM_APP):
  1525. if item.properties[iItemPropActive]:
  1526. gDBus.ladish_app_iface.StopApp(item.properties[iItemPropNumber])
  1527. else:
  1528. gDBus.ladish_app_iface.StartApp(item.properties[iItemPropNumber])
  1529. @pyqtSlot()
  1530. def slot_updateMenuStudioList_Load(self):
  1531. self.ui.menu_studio_load.clear()
  1532. studio_list = gDBus.ladish_control.GetStudioList()
  1533. if len(studio_list) == 0:
  1534. act_no_studio = QAction(self.tr("Empty studio list"), self.ui.menu_studio_load)
  1535. act_no_studio.setEnabled(False)
  1536. self.ui.menu_studio_load.addAction(act_no_studio)
  1537. else:
  1538. for studio in studio_list:
  1539. studio_name = str(studio[iStudioListName])
  1540. act_x_studio = QAction(studio_name, self.ui.menu_studio_load)
  1541. act_x_studio.setProperty("data", studio_name);
  1542. self.ui.menu_studio_load.addAction(act_x_studio)
  1543. act_x_studio.triggered.connect(self.slot_studio_load_m)
  1544. @pyqtSlot()
  1545. def slot_updateMenuStudioList_Delete(self):
  1546. self.ui.menu_studio_delete.clear()
  1547. studio_list = gDBus.ladish_control.GetStudioList()
  1548. if len(studio_list) == 0:
  1549. act_no_studio = QAction(self.tr("Empty studio list"), self.ui.menu_studio_delete)
  1550. act_no_studio.setEnabled(False)
  1551. self.ui.menu_studio_delete.addAction(act_no_studio)
  1552. else:
  1553. for studio in studio_list:
  1554. studio_name = str(studio[iStudioListName])
  1555. act_x_studio = QAction(studio_name, self.ui.menu_studio_delete)
  1556. act_x_studio.setProperty("data", studio_name);
  1557. self.ui.menu_studio_delete.addAction(act_x_studio)
  1558. act_x_studio.triggered.connect(self.slot_studio_delete_m)
  1559. @pyqtSlot()
  1560. def slot_updateMenuRoomList(self):
  1561. self.ui.menu_room_delete.clear()
  1562. if gDBus.ladish_control.IsStudioLoaded():
  1563. room_list = gDBus.ladish_studio.GetRoomList()
  1564. if len(room_list) == 0:
  1565. self.createEmptyMenuRoomActon()
  1566. else:
  1567. for room_path, room_dict in room_list:
  1568. ladish_room = gDBus.bus.get_object("org.ladish", room_path)
  1569. room_name = ladish_room.GetName()
  1570. act_x_room = QAction(room_name, self.ui.menu_room_delete)
  1571. act_x_room.setProperty("data", room_name);
  1572. self.ui.menu_room_delete.addAction(act_x_room)
  1573. act_x_room.triggered.connect(self.slot_room_delete_m)
  1574. else:
  1575. self.createEmptyMenuRoomActon()
  1576. def createEmptyMenuRoomActon(self):
  1577. act_no_room = QAction(self.tr("Empty room list"), self.ui.menu_room_delete)
  1578. act_no_room.setEnabled(False)
  1579. self.ui.menu_room_delete.addAction(act_no_room)
  1580. @pyqtSlot()
  1581. def slot_updateMenuProjectList(self):
  1582. self.ui.menu_project_load.clear()
  1583. act_project_load = QAction(self.tr("Load from folder..."), self.ui.menu_project_load)
  1584. self.ui.menu_project_load.addAction(act_project_load)
  1585. act_project_load.triggered.connect(self.slot_project_load)
  1586. ladish_recent_iface = dbus.Interface(gDBus.ladish_room, "org.ladish.RecentItems")
  1587. proj_list = ladish_recent_iface.get(RECENT_PROJECTS_STORE_MAX_ITEMS)
  1588. if len(proj_list) > 0:
  1589. self.ui.menu_project_load.addSeparator()
  1590. for proj_path, proj_dict in proj_list:
  1591. if "name" in proj_dict.keys():
  1592. proj_name = proj_dict['name']
  1593. else:
  1594. continue
  1595. act_x_text = "%s [%s]" % (proj_name, proj_path)
  1596. act_x_proj = QAction(act_x_text, self.ui.menu_project_load)
  1597. act_x_proj.setProperty("data", act_x_text);
  1598. self.ui.menu_project_load.addAction(act_x_proj)
  1599. act_x_proj.triggered.connect(self.slot_project_load_m)
  1600. @pyqtSlot()
  1601. def slot_showAppListCustomMenu(self):
  1602. item = self.ui.treeWidget.currentItem()
  1603. if item:
  1604. cMenu = QMenu()
  1605. if item.type() == ITEM_TYPE_STUDIO:
  1606. act_x_add_new = cMenu.addAction(self.tr("Add New..."))
  1607. act_x_run_custom = cMenu.addAction(self.tr("Run Custom..."))
  1608. cMenu.addSeparator()
  1609. act_x_create_room = cMenu.addAction(self.tr("Create Room..."))
  1610. act_x_add_new.setIcon(QIcon.fromTheme("list-add", QIcon(":/16x16/list-add.png")))
  1611. act_x_run_custom.setIcon(QIcon.fromTheme("system-run", QIcon(":/16x16/system-run.png")))
  1612. act_x_create_room.setIcon(QIcon.fromTheme("list-add", QIcon(":/16x16/list-add.png")))
  1613. act_x_add_new.setEnabled(self.ui.act_app_add_new.isEnabled())
  1614. elif item.type() == ITEM_TYPE_ROOM:
  1615. act_x_add_new = cMenu.addAction(self.tr("Add New..."))
  1616. act_x_run_custom = cMenu.addAction(self.tr("Run Custom..."))
  1617. cMenu.addSeparator()
  1618. act_x_new = cMenu.addAction(self.tr("New Project..."))
  1619. cMenu.addMenu(self.ui.menu_project_load)
  1620. act_x_save = cMenu.addAction(self.tr("Save Project"))
  1621. act_x_save_as = cMenu.addAction(self.tr("Save Project As..."))
  1622. act_x_unload = cMenu.addAction(self.tr("Unload Project"))
  1623. cMenu.addSeparator()
  1624. act_x_properties = cMenu.addAction(self.tr("Project Properties..."))
  1625. cMenu.addSeparator()
  1626. act_x_delete_room = cMenu.addAction(self.tr("Delete Room"))
  1627. act_x_add_new.setIcon(QIcon.fromTheme("list-add", QIcon(":/16x16/list-add.png")))
  1628. act_x_run_custom.setIcon(QIcon.fromTheme("system-run", QIcon(":/16x16/system-run.png")))
  1629. act_x_new.setIcon(QIcon.fromTheme("document-new", QIcon(":/16x16/document-new.png")))
  1630. act_x_save.setIcon(QIcon.fromTheme("document-save", QIcon(":/16x16/document-save.png")))
  1631. act_x_save_as.setIcon(QIcon.fromTheme("document-save-as", QIcon(":/16x16/document-save-as.png")))
  1632. act_x_unload.setIcon(QIcon.fromTheme("window-close", QIcon(":/16x16/dialog-close.png")))
  1633. act_x_properties.setIcon(QIcon.fromTheme("edit-rename", QIcon(":/16x16/edit-rename.png")))
  1634. act_x_delete_room.setIcon(QIcon.fromTheme("edit-delete", QIcon(":/16x16/edit-delete.png")))
  1635. act_x_add_new.setEnabled(self.ui.menu_Application.isEnabled() and self.ui.act_app_add_new.isEnabled())
  1636. project_graph_version, project_properties = gDBus.ladish_room.GetProjectProperties()
  1637. if len(project_properties) == 0:
  1638. act_x_run_custom.setEnabled(False)
  1639. act_x_save.setEnabled(False)
  1640. act_x_save_as.setEnabled(False)
  1641. act_x_unload.setEnabled(False)
  1642. act_x_properties.setEnabled(False)
  1643. elif item.type() in (ITEM_TYPE_STUDIO_APP, ITEM_TYPE_ROOM_APP):
  1644. if item.properties[iItemPropActive]:
  1645. act_x_start = None
  1646. act_x_stop = cMenu.addAction(self.tr("Stop"))
  1647. act_x_kill = cMenu.addAction(self.tr("Kill"))
  1648. act_x_stop.setIcon(QIcon.fromTheme("media-playback-stop", QIcon(":/16x16/media-playback-stop.png")))
  1649. act_x_kill.setIcon(QIcon.fromTheme("dialog-close", QIcon(":/16x16/dialog-close.png")))
  1650. else:
  1651. act_x_start = cMenu.addAction(self.tr("Start"))
  1652. act_x_stop = None
  1653. act_x_kill = None
  1654. act_x_start.setIcon(QIcon.fromTheme("media-playback-start", QIcon(":/16x16/media-playback-start.png")))
  1655. act_x_properties = cMenu.addAction(self.tr("Properties"))
  1656. cMenu.addSeparator()
  1657. act_x_remove = cMenu.addAction(self.tr("Remove"))
  1658. act_x_properties.setIcon(QIcon.fromTheme("edit-rename", QIcon(":/16x16/edit-rename.png")))
  1659. act_x_remove.setIcon(QIcon.fromTheme("edit-delete", QIcon(":/16x16/edit-delete.png")))
  1660. else:
  1661. return
  1662. act_x_sel = cMenu.exec_(QCursor.pos())
  1663. if act_x_sel:
  1664. if item.type() == ITEM_TYPE_STUDIO:
  1665. if act_x_sel == act_x_add_new:
  1666. self.slot_app_add_new()
  1667. elif act_x_sel == act_x_run_custom:
  1668. self.slot_app_run_custom()
  1669. elif act_x_sel == act_x_create_room:
  1670. self.slot_room_create()
  1671. elif item.type() == ITEM_TYPE_ROOM:
  1672. if act_x_sel == act_x_add_new:
  1673. self.slot_app_add_new()
  1674. elif act_x_sel == act_x_run_custom:
  1675. self.slot_app_run_custom()
  1676. elif act_x_sel == act_x_new:
  1677. self.slot_project_new()
  1678. elif act_x_sel == act_x_save:
  1679. self.slot_project_save()
  1680. elif act_x_sel == act_x_save_as:
  1681. self.slot_project_save_as()
  1682. elif act_x_sel == act_x_unload:
  1683. self.slot_project_unload()
  1684. elif act_x_sel == act_x_properties:
  1685. self.slot_project_properties()
  1686. elif act_x_sel == act_x_delete_room:
  1687. room_name = gDBus.ladish_room.GetName()
  1688. gDBus.ladish_studio.DeleteRoom(room_name)
  1689. elif item.type() in (ITEM_TYPE_STUDIO_APP, ITEM_TYPE_ROOM_APP):
  1690. number = item.properties[iItemPropNumber]
  1691. if act_x_sel == act_x_start:
  1692. gDBus.ladish_app_iface.StartApp(number)
  1693. elif act_x_sel == act_x_stop:
  1694. gDBus.ladish_app_iface.StopApp(number)
  1695. elif act_x_sel == act_x_kill:
  1696. gDBus.ladish_app_iface.KillApp(number)
  1697. elif act_x_sel == act_x_properties:
  1698. name, command, active, terminal, level = gDBus.ladish_app_iface.GetAppProperties2(number)
  1699. app_obj = [None, None, None, None, None]
  1700. app_obj[iAppCommand] = str(command)
  1701. app_obj[iAppName] = str(name)
  1702. app_obj[iAppTerminal] = bool(terminal)
  1703. app_obj[iAppLevel] = str(level)
  1704. app_obj[iAppActive] = bool(active)
  1705. dialog = RunCustomW(self, bool(item.type() == ITEM_TYPE_ROOM_APP), app_obj)
  1706. dialog.setWindowTitle(self.tr("App properties"))
  1707. if dialog.exec_():
  1708. app_obj = dialog.ret_app_obj
  1709. gDBus.ladish_app_iface.SetAppProperties2(number, app_obj[iAppName], app_obj[iAppCommand], app_obj[iAppTerminal], app_obj[iAppLevel])
  1710. elif act_x_sel == act_x_remove:
  1711. gDBus.ladish_app_iface.RemoveApp(number)
  1712. @pyqtSlot(float)
  1713. def slot_canvasScaleChanged(self, scale):
  1714. self.ui.miniCanvasPreview.setViewScale(scale)
  1715. @pyqtSlot(int, int, QPointF)
  1716. def slot_canvasItemMoved(self, group_id, split_mode, pos):
  1717. if split_mode == patchcanvas.PORT_MODE_INPUT:
  1718. canvas_x = URI_CANVAS_X_SPLIT
  1719. canvas_y = URI_CANVAS_Y_SPLIT
  1720. else:
  1721. canvas_x = URI_CANVAS_X
  1722. canvas_y = URI_CANVAS_Y
  1723. gDBus.ladish_graph.Set(GRAPH_DICT_OBJECT_TYPE_CLIENT, group_id, canvas_x, str(pos.x()))
  1724. gDBus.ladish_graph.Set(GRAPH_DICT_OBJECT_TYPE_CLIENT, group_id, canvas_y, str(pos.y()))
  1725. self.ui.miniCanvasPreview.update()
  1726. @pyqtSlot(int)
  1727. def slot_horizontalScrollBarChanged(self, value):
  1728. maximum = self.ui.graphicsView.horizontalScrollBar().maximum()
  1729. if maximum == 0:
  1730. xp = 0
  1731. else:
  1732. xp = float(value) / maximum
  1733. self.ui.miniCanvasPreview.setViewPosX(xp)
  1734. @pyqtSlot(int)
  1735. def slot_verticalScrollBarChanged(self, value):
  1736. maximum = self.ui.graphicsView.verticalScrollBar().maximum()
  1737. if maximum == 0:
  1738. yp = 0
  1739. else:
  1740. yp = float(value) / maximum
  1741. self.ui.miniCanvasPreview.setViewPosY(yp)
  1742. @pyqtSlot()
  1743. def slot_miniCanvasInit(self):
  1744. settings = QSettings()
  1745. self.ui.graphicsView.horizontalScrollBar().setValue(settings.value("HorizontalScrollBarValue", int(DEFAULT_CANVAS_WIDTH / 3), type=int))
  1746. self.ui.graphicsView.verticalScrollBar().setValue(settings.value("VerticalScrollBarValue", int(DEFAULT_CANVAS_HEIGHT * 3 / 8), type=int))
  1747. @pyqtSlot(float, float)
  1748. def slot_miniCanvasMoved(self, xp, yp):
  1749. self.ui.graphicsView.horizontalScrollBar().setValue(int(xp * DEFAULT_CANVAS_WIDTH))
  1750. self.ui.graphicsView.verticalScrollBar().setValue(int(yp * DEFAULT_CANVAS_HEIGHT))
  1751. @pyqtSlot()
  1752. def slot_miniCanvasCheckAll(self):
  1753. self.slot_miniCanvasCheckSize()
  1754. self.slot_horizontalScrollBarChanged(self.ui.graphicsView.horizontalScrollBar().value())
  1755. self.slot_verticalScrollBarChanged(self.ui.graphicsView.verticalScrollBar().value())
  1756. @pyqtSlot()
  1757. def slot_miniCanvasCheckSize(self):
  1758. self.ui.miniCanvasPreview.setViewSize(float(self.ui.graphicsView.width()) / DEFAULT_CANVAS_WIDTH,
  1759. float(self.ui.graphicsView.height()) / DEFAULT_CANVAS_HEIGHT)
  1760. @pyqtSlot()
  1761. def slot_handleCrash_jack(self):
  1762. patchcanvas.clear()
  1763. self.DBusReconnect()
  1764. self.studioUnloaded()
  1765. if gDBus.a2j:
  1766. if gDBus.a2j.is_started():
  1767. self.a2jStarted()
  1768. else:
  1769. self.a2jStopped()
  1770. else:
  1771. self.ui.act_tools_a2j_start.setEnabled(False)
  1772. self.ui.act_tools_a2j_stop.setEnabled(False)
  1773. self.ui.act_tools_a2j_export_hw.setEnabled(False)
  1774. self.ui.menu_A2J_Bridge.setEnabled(False)
  1775. @pyqtSlot()
  1776. def slot_handleCrash_ladish(self):
  1777. self.ui.treeWidget.clear()
  1778. patchcanvas.clear()
  1779. self.DBusReconnect()
  1780. QMessageBox.warning(self, self.tr("Error"), self.tr("ladish daemon has crashed"))
  1781. @pyqtSlot()
  1782. def slot_handleCrash_studio(self):
  1783. QMessageBox.warning(self, self.tr("Error"), self.tr("jackdbus has crashed"))
  1784. @pyqtSlot()
  1785. def slot_handleCrash_a2j(self):
  1786. try:
  1787. gDBus.a2j = dbus.Interface(gDBus.bus.get_object("org.gna.home.a2jmidid", "/"), "org.gna.home.a2jmidid.control")
  1788. except:
  1789. gDBus.a2j = None
  1790. if gDBus.a2j:
  1791. if gDBus.a2j.is_started():
  1792. self.a2jStarted()
  1793. else:
  1794. self.a2jStopped()
  1795. else:
  1796. self.ui.act_tools_a2j_start.setEnabled(False)
  1797. self.ui.act_tools_a2j_stop.setEnabled(False)
  1798. self.ui.act_tools_a2j_export_hw.setEnabled(False)
  1799. self.ui.menu_A2J_Bridge.setEnabled(False)
  1800. @pyqtSlot(str)
  1801. def slot_DBusCrashCallback(self, appInterface):
  1802. if appInterface == "org.jackaudio.service":
  1803. if not (self.m_crashedJACK or self.m_crashedLADISH):
  1804. self.m_crashedJACK = True
  1805. QTimer.singleShot(1000, self.slot_handleCrash_jack)
  1806. elif appInterface == "org.ladish":
  1807. if not (self.m_crashedJACK or self.m_crashedLADISH):
  1808. self.m_crashedLADISH = True
  1809. QTimer.singleShot(1000, self.slot_handleCrash_ladish)
  1810. @pyqtSlot()
  1811. def slot_DBusServerStartedCallback(self):
  1812. self.jackStarted()
  1813. @pyqtSlot()
  1814. def slot_DBusServerStoppedCallback(self):
  1815. self.jackStopped()
  1816. @pyqtSlot(int, str)
  1817. def slot_DBusClientAppearedCallback(self, group_id, group_name):
  1818. self.canvas_add_group(group_id, group_name)
  1819. @pyqtSlot(int)
  1820. def slot_DBusClientDisappearedCallback(self, group_id):
  1821. self.canvas_remove_group(group_id)
  1822. @pyqtSlot(int, str)
  1823. def slot_DBusClientRenamedCallback(self, group_id, new_group_name):
  1824. self.canvas_rename_group(group_id, new_group_name)
  1825. @pyqtSlot(int, int, str, int, int)
  1826. def slot_DBusPortAppearedCallback(self, group_id, port_id, port_name, port_flags, port_type_jack):
  1827. if port_flags & JACKDBUS_PORT_FLAG_INPUT:
  1828. port_mode = patchcanvas.PORT_MODE_INPUT
  1829. elif port_flags & JACKDBUS_PORT_FLAG_OUTPUT:
  1830. port_mode = patchcanvas.PORT_MODE_OUTPUT
  1831. else:
  1832. port_mode = patchcanvas.PORT_MODE_NULL
  1833. if port_type_jack == JACKDBUS_PORT_TYPE_AUDIO:
  1834. port_type = patchcanvas.PORT_TYPE_AUDIO_JACK
  1835. elif port_type_jack == JACKDBUS_PORT_TYPE_MIDI:
  1836. if gDBus.ladish_graph.Get(GRAPH_DICT_OBJECT_TYPE_PORT, port_id, URI_A2J_PORT) == "yes":
  1837. port_type = patchcanvas.PORT_TYPE_MIDI_A2J
  1838. else:
  1839. port_type = patchcanvas.PORT_TYPE_MIDI_JACK
  1840. else:
  1841. port_type = patchcanvas.PORT_TYPE_NULL
  1842. self.canvas_add_port(group_id, port_id, port_name, port_mode, port_type)
  1843. @pyqtSlot(int)
  1844. def slot_DBusPortDisppearedCallback(self, port_id):
  1845. self.canvas_remove_port(port_id)
  1846. @pyqtSlot(int, str)
  1847. def slot_DBusPortRenamedCallback(self, port_id, new_port_name):
  1848. self.canvas_rename_port(port_id, new_port_name)
  1849. @pyqtSlot(int, int, int)
  1850. def slot_DBusPortsConnectedCallback(self, connection_id, source_port_id, target_port_id):
  1851. self.canvas_connect_ports(connection_id, source_port_id, target_port_id)
  1852. @pyqtSlot(int)
  1853. def slot_DBusPortsDisconnectedCallback(self, connection_id):
  1854. self.canvas_disconnect_ports(connection_id)
  1855. @pyqtSlot()
  1856. def slot_DBusStudioAppearedCallback(self):
  1857. self.studioLoaded()
  1858. if gDBus.ladish_studio.IsStarted():
  1859. self.studioStarted()
  1860. else:
  1861. self.studioStopped()
  1862. @pyqtSlot()
  1863. def slot_DBusStudioDisappearedCallback(self):
  1864. self.studioUnloaded()
  1865. @pyqtSlot()
  1866. def slot_DBusQueueExecutionHaltedCallback(self):
  1867. log_path = os.path.join(HOME, ".log", "ladish", "ladish.log")
  1868. if os.path.exists(log_path):
  1869. log_file = open(log_path)
  1870. log_text = logs.fixLogText(log_file.read().split("ERROR: ")[-1].split("\n")[0])
  1871. log_file.close()
  1872. else:
  1873. log_text = None
  1874. msgbox = QMessageBox(QMessageBox.Critical, self.tr("Execution Halted"),
  1875. self.tr("Something went wrong with ladish so the last action was not sucessful.\n"), QMessageBox.Ok, self)
  1876. if log_text:
  1877. msgbox.setInformativeText(self.tr("You can check the ladish log file (or click in the 'Show Details' button) to find out what went wrong."))
  1878. msgbox.setDetailedText(log_text)
  1879. else:
  1880. msgbox.setInformativeText(self.tr("You can check the ladish log file to find out what went wrong."))
  1881. msgbox.show()
  1882. @pyqtSlot()
  1883. def slot_DBusCleanExitCallback(self):
  1884. pass # TODO
  1885. #self.timer1000.stop()
  1886. #QTimer.singleShot(1000, self.DBusReconnect)
  1887. #QTimer.singleShot(1500, self.timer1000.start)
  1888. @pyqtSlot()
  1889. def slot_DBusStudioStartedCallback(self):
  1890. self.studioStarted()
  1891. @pyqtSlot()
  1892. def slot_DBusStudioStoppedCallback(self):
  1893. self.studioStopped()
  1894. @pyqtSlot(str)
  1895. def slot_DBusStudioRenamedCallback(self, new_name):
  1896. self.ui.treeWidget.topLevelItem(0).setText(0, new_name)
  1897. @pyqtSlot()
  1898. def slot_DBusStudioCrashedCallback(self):
  1899. QTimer.singleShot(0, self.slot_handleCrash_studio)
  1900. @pyqtSlot(str, str)
  1901. def slot_DBusRoomAppearedCallback(self, room_path, room_name):
  1902. self.room_add(room_path, room_name)
  1903. @pyqtSlot(str)
  1904. def slot_DBusRoomDisappearedCallback(self, room_path):
  1905. for i in range(self.ui.treeWidget.topLevelItemCount()):
  1906. item = self.ui.treeWidget.topLevelItem(i)
  1907. if i == 0:
  1908. continue
  1909. if item and item.type() == ITEM_TYPE_ROOM and item.properties[iItemPropRoomPath] == room_path:
  1910. for j in range(item.childCount()):
  1911. item.takeChild(j)
  1912. self.ui.treeWidget.takeTopLevelItem(i)
  1913. break
  1914. else:
  1915. print("Claudia - room delete failed")
  1916. @pyqtSlot()
  1917. def slot_DBusRoomChangedCallback(self):
  1918. # Unused in ladish v1.0
  1919. return
  1920. @pyqtSlot(str, str)
  1921. def slot_DBusProjectPropertiesChanged(self, path, name):
  1922. has_project = bool(name)
  1923. if has_project:
  1924. item_string = " (%s)" % name
  1925. else:
  1926. item_string = ""
  1927. self.ui.act_project_save.setEnabled(has_project)
  1928. self.ui.act_project_save_as.setEnabled(has_project)
  1929. self.ui.act_project_unload.setEnabled(has_project)
  1930. self.ui.act_project_properties.setEnabled(has_project)
  1931. self.ui.b_project_save.setEnabled(has_project)
  1932. self.ui.b_project_save_as.setEnabled(has_project)
  1933. self.ui.menu_Application.setEnabled(has_project)
  1934. if path == "/org/ladish/Studio":
  1935. top_level_item = self.ui.treeWidget.topLevelItem(0)
  1936. room_name = ""
  1937. else:
  1938. for i in range(self.ui.treeWidget.topLevelItemCount()):
  1939. if i == 0:
  1940. continue
  1941. top_level_item = self.ui.treeWidget.topLevelItem(i)
  1942. if top_level_item and top_level_item.type() == ITEM_TYPE_ROOM and top_level_item.properties[iItemPropRoomPath] == path:
  1943. room_name = top_level_item.properties[iItemPropRoomName]
  1944. break
  1945. else:
  1946. return
  1947. top_level_item.setText(0, "%s%s" % (room_name, item_string))
  1948. @pyqtSlot(str, int, str, bool, bool, str)
  1949. def slot_DBusAppAdded2Callback(self, path, number, name, active, terminal, level):
  1950. if path == "/org/ladish/Studio":
  1951. ITEM_TYPE = ITEM_TYPE_STUDIO_APP
  1952. top_level_item = self.ui.treeWidget.topLevelItem(0)
  1953. else:
  1954. ITEM_TYPE = ITEM_TYPE_ROOM_APP
  1955. for i in range(self.ui.treeWidget.topLevelItemCount()):
  1956. if i == 0:
  1957. continue
  1958. top_level_item = self.ui.treeWidget.topLevelItem(i)
  1959. if top_level_item and top_level_item.type() == ITEM_TYPE_ROOM and top_level_item.properties[iItemPropRoomPath] == path:
  1960. break
  1961. else:
  1962. return
  1963. for i in range(top_level_item.childCount()):
  1964. if top_level_item.child(i).properties[iItemPropNumber] == number:
  1965. # App was added before, probably during reload/init
  1966. return
  1967. prop_obj = [None, None, None, None, None]
  1968. prop_obj[iItemPropNumber] = number
  1969. prop_obj[iItemPropName] = name
  1970. prop_obj[iItemPropActive] = active
  1971. prop_obj[iItemPropTerminal] = terminal
  1972. prop_obj[iItemPropLevel] = level
  1973. text = "["
  1974. if level.isdigit():
  1975. text += "L%s" % level
  1976. elif level == "jacksession":
  1977. text += "JS"
  1978. else:
  1979. text += level.upper()
  1980. text += "] "
  1981. if not active:
  1982. text += "(inactive) "
  1983. text += name
  1984. item = QTreeWidgetItem(ITEM_TYPE)
  1985. item.properties = prop_obj
  1986. item.setText(0, text)
  1987. top_level_item.addChild(item)
  1988. @pyqtSlot(str, int)
  1989. def slot_DBusAppRemovedCallback(self, path, number):
  1990. if path == "/org/ladish/Studio":
  1991. top_level_item = self.ui.treeWidget.topLevelItem(0)
  1992. else:
  1993. for i in range(self.ui.treeWidget.topLevelItemCount()):
  1994. if i == 0:
  1995. continue
  1996. top_level_item = self.ui.treeWidget.topLevelItem(i)
  1997. if top_level_item and top_level_item.type() == ITEM_TYPE_ROOM and top_level_item.properties[iItemPropRoomPath] == path:
  1998. break
  1999. else:
  2000. return
  2001. for i in range(top_level_item.childCount()):
  2002. if top_level_item.child(i).properties[iItemPropNumber] == number:
  2003. top_level_item.takeChild(i)
  2004. break
  2005. @pyqtSlot(str, int, str, bool, bool, str)
  2006. def slot_DBusAppStateChanged2Callback(self, path, number, name, active, terminal, level):
  2007. if path == "/org/ladish/Studio":
  2008. top_level_item = self.ui.treeWidget.topLevelItem(0)
  2009. else:
  2010. for i in range(self.ui.treeWidget.topLevelItemCount()):
  2011. if i == 0:
  2012. continue
  2013. top_level_item = self.ui.treeWidget.topLevelItem(i)
  2014. if top_level_item and top_level_item.type() == ITEM_TYPE_ROOM and top_level_item.properties[iItemPropRoomPath] == path:
  2015. break
  2016. else:
  2017. return
  2018. prop_obj = [None, None, None, None, None]
  2019. prop_obj[iItemPropNumber] = number
  2020. prop_obj[iItemPropName] = name
  2021. prop_obj[iItemPropActive] = active
  2022. prop_obj[iItemPropTerminal] = terminal
  2023. prop_obj[iItemPropLevel] = level
  2024. text = "["
  2025. if level.isdigit():
  2026. text += "L%s" % level
  2027. elif level == "jacksession":
  2028. text += "JS"
  2029. else:
  2030. text += level.upper()
  2031. text += "] "
  2032. if not active:
  2033. text += "(inactive) "
  2034. text += name
  2035. for i in range(top_level_item.childCount()):
  2036. item = top_level_item.child(i)
  2037. if item.properties[iItemPropNumber] == number:
  2038. item.properties = prop_obj
  2039. item.setText(0, text)
  2040. break
  2041. @pyqtSlot()
  2042. def slot_JackClearXruns(self):
  2043. if gJack.client:
  2044. gDBus.jack.ResetXruns()
  2045. @pyqtSlot(int)
  2046. def slot_JackBufferSizeCallback(self, bufferSize):
  2047. self.ui_setBufferSize(bufferSize)
  2048. @pyqtSlot(int)
  2049. def slot_JackSampleRateCallback(self, sampleRate):
  2050. self.ui_setSampleRate(sampleRate)
  2051. @pyqtSlot()
  2052. def slot_JackShutdownCallback(self):
  2053. self.jackStopped()
  2054. @pyqtSlot()
  2055. def slot_A2JBridgeStart(self):
  2056. ret = False
  2057. if gDBus.a2j:
  2058. ret = bool(gDBus.a2j.start())
  2059. return ret
  2060. @pyqtSlot()
  2061. def slot_A2JBridgeStop(self):
  2062. ret = False
  2063. if gDBus.a2j:
  2064. ret = bool(gDBus.a2j.stop())
  2065. return ret
  2066. @pyqtSlot()
  2067. def slot_A2JBridgeExportHW(self):
  2068. if gDBus.a2j:
  2069. ask = QMessageBox.question(self, self.tr("A2J Hardware Export"), self.tr("Enable Hardware Export on the A2J Bridge?"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.No)
  2070. if ask == QMessageBox.Yes:
  2071. gDBus.a2j.set_hw_export(True)
  2072. elif ask == QMessageBox.No:
  2073. gDBus.a2j.set_hw_export(False)
  2074. @pyqtSlot()
  2075. def slot_configureClaudia(self):
  2076. # Save groups position now
  2077. if gDBus.patchbay:
  2078. version, groups, conns = gDBus.patchbay.GetGraph(0)
  2079. for group in groups:
  2080. group_id, group_name, ports = group
  2081. group_pos_i = patchcanvas.getGroupPos(group_id, patchcanvas.PORT_MODE_OUTPUT)
  2082. group_pos_o = patchcanvas.getGroupPos(group_id, patchcanvas.PORT_MODE_INPUT)
  2083. gDBus.ladish_graph.Set(GRAPH_DICT_OBJECT_TYPE_CLIENT, group_id, URI_CANVAS_X, str(group_pos_o.x()))
  2084. gDBus.ladish_graph.Set(GRAPH_DICT_OBJECT_TYPE_CLIENT, group_id, URI_CANVAS_Y, str(group_pos_o.y()))
  2085. gDBus.ladish_graph.Set(GRAPH_DICT_OBJECT_TYPE_CLIENT, group_id, URI_CANVAS_X_SPLIT, str(group_pos_i.x()))
  2086. gDBus.ladish_graph.Set(GRAPH_DICT_OBJECT_TYPE_CLIENT, group_id, URI_CANVAS_Y_SPLIT, str(group_pos_i.y()))
  2087. try:
  2088. ladish_config = gDBus.bus.get_object("org.ladish.conf", "/org/ladish/conf")
  2089. except:
  2090. ladish_config = None
  2091. if ladish_config:
  2092. try:
  2093. key_notify = bool(ladish_config.get(LADISH_CONF_KEY_DAEMON_NOTIFY)[0] == "true")
  2094. except:
  2095. key_notify = LADISH_CONF_KEY_DAEMON_NOTIFY_DEFAULT
  2096. try:
  2097. key_shell = str(ladish_config.get(LADISH_CONF_KEY_DAEMON_SHELL)[0])
  2098. except:
  2099. key_shell = LADISH_CONF_KEY_DAEMON_SHELL_DEFAULT
  2100. try:
  2101. key_terminal = str(ladish_config.get(LADISH_CONF_KEY_DAEMON_TERMINAL)[0])
  2102. except:
  2103. key_terminal = LADISH_CONF_KEY_DAEMON_TERMINAL_DEFAULT
  2104. try:
  2105. key_studio_autostart = bool(ladish_config.get(LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART)[0] == "true")
  2106. except:
  2107. key_studio_autostart = LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART_DEFAULT
  2108. try:
  2109. key_js_save_delay = int(ladish_config.get(LADISH_CONF_KEY_DAEMON_JS_SAVE_DELAY)[0])
  2110. except:
  2111. key_js_save_delay = LADISH_CONF_KEY_DAEMON_JS_SAVE_DELAY_DEFAULT
  2112. settings = QSettings()
  2113. settings.setValue(LADISH_CONF_KEY_DAEMON_NOTIFY, key_notify)
  2114. settings.setValue(LADISH_CONF_KEY_DAEMON_SHELL, key_shell)
  2115. settings.setValue(LADISH_CONF_KEY_DAEMON_TERMINAL, key_terminal)
  2116. settings.setValue(LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART, key_studio_autostart)
  2117. settings.setValue(LADISH_CONF_KEY_DAEMON_JS_SAVE_DELAY, key_js_save_delay)
  2118. del settings
  2119. dialog = SettingsW(self, "claudia", hasGL)
  2120. if not ladish_config:
  2121. dialog.ui.lw_page.hideRow(2)
  2122. if dialog.exec_():
  2123. if ladish_config:
  2124. settings = QSettings()
  2125. ladish_config.set(LADISH_CONF_KEY_DAEMON_NOTIFY, "true" if (settings.value(LADISH_CONF_KEY_DAEMON_NOTIFY, LADISH_CONF_KEY_DAEMON_NOTIFY_DEFAULT, type=bool)) else "false")
  2126. ladish_config.set(LADISH_CONF_KEY_DAEMON_SHELL, settings.value(LADISH_CONF_KEY_DAEMON_SHELL, LADISH_CONF_KEY_DAEMON_SHELL_DEFAULT, type=str))
  2127. ladish_config.set(LADISH_CONF_KEY_DAEMON_TERMINAL, settings.value(LADISH_CONF_KEY_DAEMON_TERMINAL, LADISH_CONF_KEY_DAEMON_TERMINAL_DEFAULT, type=str))
  2128. ladish_config.set(LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART, "true" if (settings.value(LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART, LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART_DEFAULT, type=bool)) else "false")
  2129. ladish_config.set(LADISH_CONF_KEY_DAEMON_JS_SAVE_DELAY, str(settings.value(LADISH_CONF_KEY_DAEMON_JS_SAVE_DELAY, LADISH_CONF_KEY_DAEMON_JS_SAVE_DELAY_DEFAULT, type=int)))
  2130. del settings
  2131. self.loadSettings(False)
  2132. patchcanvas.clear()
  2133. pOptions = patchcanvas.options_t()
  2134. pOptions.theme_name = self.fSavedSettings["Canvas/Theme"]
  2135. pOptions.auto_hide_groups = self.fSavedSettings["Canvas/AutoHideGroups"]
  2136. pOptions.use_bezier_lines = self.fSavedSettings["Canvas/UseBezierLines"]
  2137. pOptions.antialiasing = self.fSavedSettings["Canvas/Antialiasing"]
  2138. pOptions.eyecandy = self.fSavedSettings["Canvas/EyeCandy"]
  2139. pFeatures = patchcanvas.features_t()
  2140. pFeatures.group_info = False
  2141. pFeatures.group_rename = True
  2142. pFeatures.port_info = True
  2143. pFeatures.port_rename = True
  2144. pFeatures.handle_group_pos = False
  2145. patchcanvas.setOptions(pOptions)
  2146. patchcanvas.setFeatures(pFeatures)
  2147. patchcanvas.init("Claudia", self.scene, self.canvasCallback, DEBUG)
  2148. self.ui.miniCanvasPreview.setViewTheme(patchcanvas.canvas.theme.canvas_bg, patchcanvas.canvas.theme.rubberband_brush, patchcanvas.canvas.theme.rubberband_pen.color())
  2149. if gDBus.ladish_control.IsStudioLoaded() and gDBus.ladish_studio and gDBus.ladish_studio.IsStarted():
  2150. self.initPorts()
  2151. @pyqtSlot()
  2152. def slot_aboutClaudia(self):
  2153. QMessageBox.about(self, self.tr("About Claudia"), self.tr("<h3>Claudia</h3>"
  2154. "<br>Version %s"
  2155. "<br>Claudia is a Graphical User Interface to LADISH.<br>"
  2156. "<br>Copyright (C) 2010-2022 falkTX" % VERSION))
  2157. def saveSettings(self):
  2158. settings = QSettings()
  2159. settings.setValue("Geometry", self.saveGeometry())
  2160. settings.setValue("SplitterSizes", self.ui.splitter.saveState())
  2161. settings.setValue("ShowToolbar", self.ui.frame_toolbar.isEnabled())
  2162. settings.setValue("ShowStatusbar", self.ui.frame_statusbar.isEnabled())
  2163. settings.setValue("TransportView", self.fCurTransportView)
  2164. settings.setValue("HorizontalScrollBarValue", self.ui.graphicsView.horizontalScrollBar().value())
  2165. settings.setValue("VerticalScrollBarValue", self.ui.graphicsView.verticalScrollBar().value())
  2166. def loadSettings(self, geometry):
  2167. settings = QSettings()
  2168. if geometry:
  2169. self.restoreGeometry(settings.value("Geometry", b""))
  2170. splitterSizes = settings.value("SplitterSizes", "")
  2171. if splitterSizes:
  2172. self.ui.splitter.restoreState(splitterSizes)
  2173. else:
  2174. self.ui.splitter.setSizes((100, 400))
  2175. showToolbar = settings.value("ShowToolbar", True, type=bool)
  2176. self.ui.act_settings_show_toolbar.setChecked(showToolbar)
  2177. self.ui.frame_toolbar.setVisible(showToolbar)
  2178. showStatusbar = settings.value("ShowStatusbar", True, type=bool)
  2179. self.ui.act_settings_show_statusbar.setChecked(showStatusbar)
  2180. self.ui.frame_statusbar.setVisible(showStatusbar)
  2181. self.setTransportView(settings.value("TransportView", TRANSPORT_VIEW_HMS, type=int))
  2182. self.fSavedSettings = {
  2183. "Main/DefaultProjectFolder": settings.value("Main/DefaultProjectFolder", DEFAULT_PROJECT_FOLDER, type=str),
  2184. "Main/UseSystemTray": settings.value("Main/UseSystemTray", True, type=bool),
  2185. "Main/CloseToTray": settings.value("Main/CloseToTray", False, type=bool),
  2186. "Main/RefreshInterval": settings.value("Main/RefreshInterval", 120, type=int),
  2187. "Canvas/Theme": settings.value("Canvas/Theme", patchcanvas.getDefaultThemeName(), type=str),
  2188. "Canvas/AutoHideGroups": settings.value("Canvas/AutoHideGroups", False, type=bool),
  2189. "Canvas/UseBezierLines": settings.value("Canvas/UseBezierLines", True, type=bool),
  2190. "Canvas/EyeCandy": settings.value("Canvas/EyeCandy", patchcanvas.EYECANDY_SMALL, type=int),
  2191. "Canvas/UseOpenGL": settings.value("Canvas/UseOpenGL", False, type=bool),
  2192. "Canvas/Antialiasing": settings.value("Canvas/Antialiasing", patchcanvas.ANTIALIASING_SMALL, type=int),
  2193. "Canvas/HighQualityAntialiasing": settings.value("Canvas/HighQualityAntialiasing", False, type=bool)
  2194. }
  2195. self.ui.act_app_add_new.setEnabled(USE_CLAUDIA_ADD_NEW)
  2196. def resizeEvent(self, event):
  2197. QTimer.singleShot(0, self.slot_miniCanvasCheckSize)
  2198. QMainWindow.resizeEvent(self, event)
  2199. def timerEvent(self, event):
  2200. if event.timerId() == self.m_timer120:
  2201. if gJack.client:
  2202. self.refreshTransport()
  2203. self.refreshXruns()
  2204. elif event.timerId() == self.m_timer600:
  2205. if gJack.client:
  2206. self.refreshDSPLoad()
  2207. else:
  2208. self.update()
  2209. QMainWindow.timerEvent(self, event)
  2210. def closeEvent(self, event):
  2211. self.saveSettings()
  2212. if self.systray:
  2213. if self.fSavedSettings["Main/CloseToTray"]:
  2214. if self.systray.handleQtCloseEvent(event):
  2215. patchcanvas.clear()
  2216. return
  2217. self.systray.close()
  2218. patchcanvas.clear()
  2219. QMainWindow.closeEvent(self, event)
  2220. #--------------- main ------------------
  2221. if __name__ == '__main__':
  2222. # App initialization
  2223. app = QApplication(sys.argv)
  2224. app.setApplicationName("Claudia")
  2225. app.setApplicationVersion(VERSION)
  2226. app.setOrganizationName("LADI")
  2227. app.setWindowIcon(QIcon(":/scalable/claudia.svg"))
  2228. setup_i18n()
  2229. if not haveDBus:
  2230. QMessageBox.critical(None, app.translate("ClaudiaMainW", "Error"), app.translate("ClaudiaMainW",
  2231. "DBus is not available, Claudia cannot start without it!"))
  2232. sys.exit(1)
  2233. gDBus.loop = DBusMainLoop(set_as_default=True)
  2234. gDBus.bus = dbus.SessionBus(mainloop=gDBus.loop)
  2235. gDBus.jack = gDBus.bus.get_object("org.jackaudio.service", "/org/jackaudio/Controller")
  2236. gDBus.ladish_control = gDBus.bus.get_object("org.ladish", "/org/ladish/Control")
  2237. try:
  2238. gDBus.ladish_app_daemon = gDBus.bus.get_object("org.ladish.appdb", "/")
  2239. except:
  2240. gDBus.ladish_app_daemon = None
  2241. try:
  2242. gDBus.a2j = dbus.Interface(gDBus.bus.get_object("org.gna.home.a2jmidid", "/"), "org.gna.home.a2jmidid.control")
  2243. except:
  2244. gDBus.a2j = None
  2245. jacksettings.initBus(gDBus.bus)
  2246. # Show GUI
  2247. gui = ClaudiaMainW()
  2248. if gui.systray and "--minimized" in app.arguments():
  2249. gui.hide()
  2250. gui.systray.setActionText("show", gui.tr("Restore"))
  2251. else:
  2252. gui.show()
  2253. # Set-up custom signal handling
  2254. setUpSignals(gui)
  2255. # App-Loop
  2256. if gui.systray:
  2257. ret = gui.systray.exec_(app)
  2258. else:
  2259. ret = app.exec_()
  2260. # Close Jack
  2261. if gJack.client:
  2262. jacklib.deactivate(gJack.client)
  2263. jacklib.client_close(gJack.client)
  2264. # Exit properly
  2265. sys.exit(ret)