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.

822 lines
35KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # JACK Settings Dialog
  4. # Copyright (C) 2010-2012 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the COPYING file
  17. # Imports (Global)
  18. from PyQt4.QtCore import pyqtSlot, Qt, QTimer, SIGNAL, SLOT
  19. from PyQt4.QtGui import QDialog, QDialogButtonBox, QMessageBox
  20. from sys import platform
  21. # Imports (Custom Stuff)
  22. import ui_settings_jack
  23. # Imports (DBus)
  24. try:
  25. import dbus
  26. except:
  27. dbus = None
  28. # -------------------------------------------------------------
  29. # global object
  30. global jackctl
  31. jackctl = None
  32. # enum jack_timer_type_t
  33. JACK_TIMER_SYSTEM_CLOCK = 0
  34. JACK_TIMER_CYCLE_COUNTER = 1
  35. JACK_TIMER_HPET = 2
  36. # Set Platform
  37. if "linux" in platform:
  38. LINUX = True
  39. from subprocess import getoutput
  40. else:
  41. LINUX = False
  42. # Init DBus
  43. def initBus(bus):
  44. global jackctl
  45. try:
  46. jackctl = dbus.Interface(bus.get_object("org.jackaudio.service", "/org/jackaudio/Controller"), "org.jackaudio.Configure")
  47. return 0
  48. except:
  49. jackctl = None
  50. return 1
  51. # -------------------------------------------------------------
  52. # Helper functions
  53. def bool2str(yesno):
  54. return "True" if yesno else "False"
  55. def getBufferSize():
  56. return getDriverParameter("period", -1)
  57. def getSampleRate():
  58. return getDriverParameter("rate", -1)
  59. def isRealtime():
  60. return getEngineParameter("realtime", False)
  61. def setBufferSize(bsize):
  62. return setDriverParameter("period", dbus.UInt32(bsize))
  63. def setSampleRate(srate):
  64. return setDriverParameter("rate", dbus.UInt32(srate))
  65. # -------------------------------------------------------------
  66. # Helper functions (engine)
  67. def engineHasFeature(feature):
  68. featureList = jackctl.ReadContainer(["engine"])[1]
  69. return bool(dbus.String(feature) in featureList)
  70. def getEngineParameter(parameter, fallback):
  71. if not engineHasFeature(parameter):
  72. return fallback
  73. else:
  74. return jackctl.GetParameterValue(["engine", parameter])[2]
  75. def setEngineParameter(parameter, value, optional=True):
  76. if not engineHasFeature(parameter):
  77. return False
  78. elif optional:
  79. if value != jackctl.GetParameterValue(["engine", parameter])[2]:
  80. return bool(jackctl.SetParameterValue(["engine", parameter], value))
  81. else:
  82. return False
  83. else:
  84. return bool(jackctl.SetParameterValue(["engine", parameter], value))
  85. # -------------------------------------------------------------
  86. # Helper functions (driver)
  87. def driverHasFeature(feature):
  88. featureList = jackctl.ReadContainer(["driver"])[1]
  89. return bool(dbus.String(feature) in featureList)
  90. def getDriverParameter(parameter, fallback):
  91. if not driverHasFeature(parameter):
  92. return fallback
  93. else:
  94. return jackctl.GetParameterValue(["driver", parameter])[2]
  95. def setDriverParameter(parameter, value, optional=True):
  96. if not driverHasFeature(parameter):
  97. return False
  98. elif optional:
  99. if value != jackctl.GetParameterValue(["driver", parameter])[2]:
  100. return bool(jackctl.SetParameterValue(["driver", parameter], value))
  101. else:
  102. return False
  103. else:
  104. return bool(jackctl.SetParameterValue(["driver", parameter], value))
  105. # -------------------------------------------------------------
  106. # JACK Settings Dialog
  107. class JackSettingsW(QDialog, ui_settings_jack.Ui_JackSettingsW):
  108. def __init__(self, parent):
  109. QDialog.__init__(self, parent)
  110. self.setupUi(self)
  111. # -------------------------------------------------------------
  112. # Check if we've got valid control interface
  113. if not jackctl:
  114. QTimer.singleShot(0, self, SLOT("slot_closeWithError()"))
  115. return
  116. # -------------------------------------------------------------
  117. # Align driver text and hide non available ones
  118. driverList = jackctl.ReadContainer(["drivers"])[1]
  119. for i in range(self.obj_server_driver.rowCount()):
  120. self.obj_server_driver.item(0, i).setTextAlignment(Qt.AlignCenter)
  121. if dbus.String(self.obj_server_driver.item(0, i).text().lower()) not in driverList:
  122. self.obj_server_driver.hideRow(i)
  123. # -------------------------------------------------------------
  124. # Set-up connections
  125. self.connect(self, SIGNAL("accepted()"), SLOT("slot_saveJackSettings()"))
  126. self.connect(self.buttonBox.button(QDialogButtonBox.Reset), SIGNAL("clicked()"), SLOT("slot_resetJackSettings()"))
  127. self.connect(self.obj_driver_duplex, SIGNAL("clicked(bool)"), SLOT("slot_checkDuplexSelection(bool)"))
  128. self.connect(self.obj_server_driver, SIGNAL("currentCellChanged(int, int, int, int)"), SLOT("slot_checkDriverSelection(int)"))
  129. self.connect(self.obj_driver_capture, SIGNAL("currentIndexChanged(int)"), SLOT("slot_checkALSASelection()"))
  130. self.connect(self.obj_driver_playback, SIGNAL("currentIndexChanged(int)"), SLOT("slot_checkALSASelection()"))
  131. # -------------------------------------------------------------
  132. # Load initial settings
  133. self.m_driver = ""
  134. self.m_server_clock_source_broken = False
  135. self.checkEngine()
  136. self.loadServerSettings()
  137. self.loadDriverSettings(True) # reset because we'll change it below
  138. # -------------------------------------------------------------
  139. # Load selected JACK driver
  140. self.m_driver = str(jackctl.GetParameterValue(["engine", "driver"])[2])
  141. for i in range(self.obj_server_driver.rowCount()):
  142. if self.obj_server_driver.item(i, 0).text().lower() == self.m_driver:
  143. self.obj_server_driver.setCurrentCell(i, 0)
  144. break
  145. # Special ALSA check
  146. self.slot_checkALSASelection()
  147. # -------------------------------------------------------------
  148. # Engine calls
  149. def checkEngine(self):
  150. self.obj_server_name.setEnabled(engineHasFeature("name"))
  151. self.obj_server_realtime.setEnabled(engineHasFeature("realtime"))
  152. self.obj_server_realtime_priority.setEnabled(engineHasFeature("realtime-priority"))
  153. self.obj_server_temporary.setEnabled(engineHasFeature("temporary"))
  154. self.obj_server_verbose.setEnabled(engineHasFeature("verbose"))
  155. self.obj_server_client_timeout.setEnabled(engineHasFeature("client-timeout"))
  156. self.obj_server_clock_source.setEnabled(engineHasFeature("clock-source"))
  157. self.obj_server_port_max.setEnabled(engineHasFeature("port-max"))
  158. self.obj_server_replace_registry.setEnabled(engineHasFeature("replace-registry"))
  159. self.obj_server_sync.setEnabled(engineHasFeature("sync"))
  160. self.obj_server_self_connect_mode.setEnabled(engineHasFeature("self-connect-mode"))
  161. # Disable clock-source if not on Linux
  162. if not LINUX:
  163. self.obj_server_clock_source.setEnabled(False)
  164. # -------------------------------------------------------------
  165. # Server calls
  166. def saveServerSettings(self):
  167. if self.obj_server_name.isEnabled():
  168. value = dbus.String(self.obj_server_name.text())
  169. setEngineParameter("name", value, True)
  170. if self.obj_server_realtime.isEnabled():
  171. value = dbus.Boolean(self.obj_server_realtime.isChecked())
  172. setEngineParameter("realtime", value, True)
  173. if self.obj_server_realtime_priority.isEnabled():
  174. value = dbus.Int32(self.obj_server_realtime_priority.value())
  175. setEngineParameter("realtime-priority", value, True)
  176. if self.obj_server_temporary.isEnabled():
  177. value = dbus.Boolean(self.obj_server_temporary.isChecked())
  178. setEngineParameter("temporary", value, True)
  179. if self.obj_server_verbose.isEnabled():
  180. value = dbus.Boolean(self.obj_server_verbose.isChecked())
  181. setEngineParameter("verbose", value, True)
  182. if self.obj_server_client_timeout.isEnabled():
  183. value = dbus.Int32(int(self.obj_server_client_timeout.currentText()))
  184. setEngineParameter("client-timeout", value, True)
  185. if self.obj_server_clock_source.isEnabled():
  186. if self.obj_server_clock_source_system.isChecked():
  187. if self.m_server_clock_source_broken:
  188. value = dbus.UInt32(JACK_TIMER_SYSTEM_CLOCK)
  189. else:
  190. value = dbus.Byte("s".encode("utf-8"))
  191. elif self.obj_server_clock_source_cycle.isChecked():
  192. if self.m_server_clock_source_broken:
  193. value = dbus.UInt32(JACK_TIMER_CYCLE_COUNTER)
  194. else:
  195. value = dbus.Byte("c".encode("utf-8"))
  196. elif self.obj_server_clock_source_hpet.isChecked():
  197. if self.m_server_clock_source_broken:
  198. value = dbus.UInt32(JACK_TIMER_HPET)
  199. else:
  200. value = dbus.Byte("h".encode("utf-8"))
  201. else:
  202. value = None
  203. print("JackSettings::saveServerSettings() - Cannot save clock-source value")
  204. if value != None:
  205. setEngineParameter("clock-source", value, True)
  206. if self.obj_server_port_max.isEnabled():
  207. value = dbus.UInt32(int(self.obj_server_port_max.currentText()))
  208. setEngineParameter("port-max", value, True)
  209. if self.obj_server_replace_registry.isEnabled():
  210. value = dbus.Boolean(self.obj_server_replace_registry.isChecked())
  211. setEngineParameter("replace-registry", value, True)
  212. if self.obj_server_sync.isEnabled():
  213. value = dbus.Boolean(self.obj_server_sync.isChecked())
  214. setEngineParameter("sync", value, True)
  215. if self.obj_server_self_connect_mode.isEnabled():
  216. if self.obj_server_self_connect_mode_0.isChecked():
  217. value = dbus.Byte(" ".encode("utf-8"))
  218. elif self.obj_server_self_connect_mode_1.isChecked():
  219. value = dbus.Byte("E".encode("utf-8"))
  220. elif self.obj_server_self_connect_mode_2.isChecked():
  221. value = dbus.Byte("e".encode("utf-8"))
  222. elif self.obj_server_self_connect_mode_3.isChecked():
  223. value = dbus.Byte("A".encode("utf-8"))
  224. elif self.obj_server_self_connect_mode_4.isChecked():
  225. value = dbus.Byte("a".encode("utf-8"))
  226. else:
  227. value = None
  228. print("JackSettings::saveServerSettings() - Cannot save self-connect-mode value")
  229. if value != None:
  230. setEngineParameter("self-connect-mode", value, True)
  231. def loadServerSettings(self, reset=False, forceReset=False):
  232. settings = jackctl.ReadContainer(["engine"])
  233. for i in range(len(settings[1])):
  234. attribute = str(settings[1][i])
  235. if reset:
  236. value = jackctl.GetParameterValue(["engine", attribute])[1]
  237. if forceReset and attribute != "driver":
  238. jackctl.ResetParameterValue(["engine", attribute])
  239. else:
  240. value = jackctl.GetParameterValue(["engine", attribute])[2]
  241. if attribute == "name":
  242. self.obj_server_name.setText(str(value))
  243. elif attribute == "realtime":
  244. self.obj_server_realtime.setChecked(bool(value))
  245. elif attribute == "realtime-priority":
  246. self.obj_server_realtime_priority.setValue(int(value))
  247. elif attribute == "temporary":
  248. self.obj_server_temporary.setChecked(bool(value))
  249. elif attribute == "verbose":
  250. self.obj_server_verbose.setChecked(bool(value))
  251. elif attribute == "client-timeout":
  252. self.setComboBoxValue(self.obj_server_client_timeout, str(value))
  253. elif attribute == "clock-source":
  254. value = str(value)
  255. if value == "c":
  256. self.obj_server_clock_source_cycle.setChecked(True)
  257. elif value == "h":
  258. self.obj_server_clock_source_hpet.setChecked(True)
  259. elif value == "s":
  260. self.obj_server_clock_source_system.setChecked(True)
  261. else:
  262. self.m_server_clock_source_broken = True
  263. if value == str(JACK_TIMER_SYSTEM_CLOCK):
  264. self.obj_server_clock_source_system.setChecked(True)
  265. elif value == str(JACK_TIMER_CYCLE_COUNTER):
  266. self.obj_server_clock_source_cycle.setChecked(True)
  267. elif value == str(JACK_TIMER_HPET):
  268. self.obj_server_clock_source_hpet.setChecked(True)
  269. else:
  270. self.obj_server_clock_source.setEnabled(False)
  271. print("JackSettings::saveServerSettings() - Invalid clock-source value '%s'" % value)
  272. elif attribute == "port-max":
  273. self.setComboBoxValue(self.obj_server_port_max, str(value))
  274. elif attribute == "replace-registry":
  275. self.obj_server_replace_registry.setChecked(bool(value))
  276. elif attribute == "sync":
  277. self.obj_server_sync.setChecked(bool(value))
  278. elif attribute == "self-connect-mode":
  279. value = str(value)
  280. if value == " ":
  281. self.obj_server_self_connect_mode_0.setChecked(True)
  282. elif value == "E":
  283. self.obj_server_self_connect_mode_1.setChecked(True)
  284. elif value == "e":
  285. self.obj_server_self_connect_mode_2.setChecked(True)
  286. elif value == "A":
  287. self.obj_server_self_connect_mode_3.setChecked(True)
  288. elif value == "a":
  289. self.obj_server_self_connect_mode_4.setChecked(True)
  290. else:
  291. self.obj_server_self_connect_mode.setEnabled(False)
  292. print("JackSettings::loadServerSettings() - Invalid self-connect-mode value '%s'" % value)
  293. elif attribute in ("driver", "slave-drivers"):
  294. pass
  295. else:
  296. print("JackSettings::loadServerSettings() - Unimplemented server attribute '%s', value: '%s'" % (attribute, str(value)))
  297. # -------------------------------------------------------------
  298. # Driver calls
  299. # resetIfNeeded: fix alsa parameter re-order bug in JACK 1.9.8 (reset/remove non-used values)
  300. def saveDriverSettings(self, resetIfNeeded):
  301. if self.obj_driver_device.isEnabled():
  302. value = dbus.String(self.obj_driver_device.currentText().split(" [")[0])
  303. if value != jackctl.GetParameterValue(["driver", "device"])[2]:
  304. jackctl.SetParameterValue(["driver", "device"], value)
  305. elif resetIfNeeded:
  306. jackctl.ResetParameterValue(["driver", "device"])
  307. if self.obj_driver_capture.isEnabled():
  308. if self.m_driver == "alsa":
  309. value = dbus.String(self.obj_driver_capture.currentText().split(" ")[0])
  310. elif self.m_driver == "dummy":
  311. value = dbus.UInt32(int(self.obj_driver_capture.currentText()))
  312. elif self.m_driver == "firewire":
  313. value = dbus.Boolean(self.obj_driver_capture.currentIndex() == 1)
  314. else:
  315. value = None
  316. print("JackSettings::saveDriverSettings() - Cannot save capture value")
  317. if value != None:
  318. setDriverParameter("capture", value, True)
  319. elif resetIfNeeded:
  320. jackctl.ResetParameterValue(["driver", "capture"])
  321. if self.obj_driver_playback.isEnabled():
  322. if self.m_driver == "alsa":
  323. value = dbus.String(self.obj_driver_playback.currentText().split(" ")[0])
  324. elif self.m_driver == "dummy":
  325. value = dbus.UInt32(int(self.obj_driver_playback.currentText()))
  326. elif self.m_driver == "firewire":
  327. value = dbus.Boolean(self.obj_driver_playback.currentIndex() == 1)
  328. else:
  329. value = None
  330. print("JackSettings::saveDriverSettings() - Cannot save playback value")
  331. if value != None:
  332. setDriverParameter("playback", value, True)
  333. elif resetIfNeeded:
  334. jackctl.ResetParameterValue(["driver", "playback"])
  335. if self.obj_driver_rate.isEnabled():
  336. value = dbus.UInt32(int(self.obj_driver_rate.currentText()))
  337. setDriverParameter("rate", value, True)
  338. if self.obj_driver_period.isEnabled():
  339. value = dbus.UInt32(int(self.obj_driver_period.currentText()))
  340. setDriverParameter("period", value, True)
  341. if self.obj_driver_nperiods.isEnabled():
  342. value = dbus.UInt32(self.obj_driver_nperiods.value())
  343. setDriverParameter("nperiods", value, True)
  344. if self.obj_driver_hwmon.isEnabled():
  345. value = dbus.Boolean(self.obj_driver_hwmon.isChecked())
  346. setDriverParameter("hwmon", value, True)
  347. if self.obj_driver_hwmeter.isEnabled():
  348. value = dbus.Boolean(self.obj_driver_hwmeter.isChecked())
  349. setDriverParameter("hwmeter", value, True)
  350. if self.obj_driver_duplex.isEnabled():
  351. value = dbus.Boolean(self.obj_driver_duplex.isChecked())
  352. setDriverParameter("duplex", value, True)
  353. if self.obj_driver_softmode.isEnabled():
  354. value = dbus.Boolean(self.obj_driver_softmode.isChecked())
  355. setDriverParameter("softmode", value, True)
  356. if self.obj_driver_monitor.isEnabled():
  357. value = dbus.Boolean(self.obj_driver_monitor.isChecked())
  358. setDriverParameter("monitor", value, True)
  359. if self.obj_driver_dither.isEnabled():
  360. if self.obj_driver_dither.currentIndex() == 0:
  361. value = dbus.Byte("n".encode("utf-8"))
  362. elif self.obj_driver_dither.currentIndex() == 1:
  363. value = dbus.Byte("r".encode("utf-8"))
  364. elif self.obj_driver_dither.currentIndex() == 2:
  365. value = dbus.Byte("s".encode("utf-8"))
  366. elif self.obj_driver_dither.currentIndex() == 3:
  367. value = dbus.Byte("t".encode("utf-8"))
  368. else:
  369. value = None
  370. print("JackSettings::saveDriverSettings() - Cannot save dither value")
  371. if value != None:
  372. setDriverParameter("dither", value, True)
  373. if self.obj_driver_inchannels.isEnabled():
  374. value = dbus.UInt32(self.obj_driver_inchannels.value())
  375. setDriverParameter("inchannels", value, True)
  376. if self.obj_driver_outchannels.isEnabled():
  377. value = dbus.UInt32(self.obj_driver_outchannels.value())
  378. setDriverParameter("outchannels", value, True)
  379. if self.obj_driver_shorts.isEnabled():
  380. value = dbus.Boolean(self.obj_driver_shorts.isChecked())
  381. setDriverParameter("shorts", value, True)
  382. if self.obj_driver_input_latency.isEnabled():
  383. value = dbus.UInt32(self.obj_driver_input_latency.value())
  384. setDriverParameter("input-latency", value, True)
  385. if self.obj_driver_output_latency.isEnabled():
  386. value = dbus.UInt32(self.obj_driver_output_latency.value())
  387. setDriverParameter("output-latency", value, True)
  388. if self.obj_driver_midi_driver.isEnabled():
  389. if self.obj_driver_midi_driver.currentIndex() == 0:
  390. value = dbus.String("none")
  391. elif self.obj_driver_midi_driver.currentIndex() == 1:
  392. value = dbus.String("seq")
  393. elif self.obj_driver_midi_driver.currentIndex() == 2:
  394. value = dbus.String("raw")
  395. else:
  396. value = None
  397. print("JackSettings::saveDriverSettings() - Cannot save midi-driver value")
  398. if value != None:
  399. if driverHasFeature("midi"):
  400. setDriverParameter("midi", value, True)
  401. else:
  402. setDriverParameter("midi-driver", value, True)
  403. if self.obj_driver_wait.isEnabled():
  404. value = dbus.UInt32(self.obj_driver_wait.value())
  405. setDriverParameter("wait", value, True)
  406. if self.obj_driver_verbose.isEnabled():
  407. value = dbus.UInt32(self.obj_driver_verbose.value())
  408. setDriverParameter("verbose", value, True)
  409. if self.obj_driver_snoop.isEnabled():
  410. value = dbus.Boolean(self.obj_driver_snoop.isChecked())
  411. setDriverParameter("snoop", value, True)
  412. if self.obj_driver_channels.isEnabled():
  413. value = dbus.Int32(self.obj_driver_channels.value())
  414. setDriverParameter("channels", value, True)
  415. def loadDriverSettings(self, reset=False, forceReset=False):
  416. settings = jackctl.ReadContainer(["driver"])
  417. for i in range(len(settings[1])):
  418. attribute = str(settings[1][i])
  419. if reset:
  420. value = jackctl.GetParameterValue(["driver", attribute])[1]
  421. if forceReset:
  422. jackctl.ResetParameterValue(["driver", attribute])
  423. else:
  424. value = jackctl.GetParameterValue(["driver", attribute])[2]
  425. if attribute == "device":
  426. self.setComboBoxValue(self.obj_driver_device, str(value), True)
  427. elif attribute == "capture":
  428. if self.m_driver == "firewire":
  429. self.obj_driver_capture.setCurrentIndex(1 if bool(value) else 0)
  430. else:
  431. self.setComboBoxValue(self.obj_driver_capture, str(value), True)
  432. elif attribute == "playback":
  433. if self.m_driver == "firewire":
  434. self.obj_driver_playback.setCurrentIndex(1 if bool(value) else 0)
  435. else:
  436. self.setComboBoxValue(self.obj_driver_playback, str(value), True)
  437. elif attribute == "rate":
  438. self.setComboBoxValue(self.obj_driver_rate, str(value))
  439. elif attribute == "period":
  440. self.setComboBoxValue(self.obj_driver_period, str(value))
  441. elif attribute == "nperiods":
  442. self.obj_driver_nperiods.setValue(int(value))
  443. elif attribute == "hwmon":
  444. self.obj_driver_hwmon.setChecked(bool(value))
  445. elif attribute == "hwmeter":
  446. self.obj_driver_hwmeter.setChecked(bool(value))
  447. elif attribute == "duplex":
  448. self.obj_driver_duplex.setChecked(bool(value))
  449. elif attribute == "softmode":
  450. self.obj_driver_softmode.setChecked(bool(value))
  451. elif attribute == "monitor":
  452. self.obj_driver_monitor.setChecked(bool(value))
  453. elif attribute == "dither":
  454. value = str(value)
  455. if value == "n":
  456. self.obj_driver_dither.setCurrentIndex(0)
  457. elif value == "r":
  458. self.obj_driver_dither.setCurrentIndex(1)
  459. elif value == "s":
  460. self.obj_driver_dither.setCurrentIndex(2)
  461. elif value == "t":
  462. self.obj_driver_dither.setCurrentIndex(3)
  463. else:
  464. self.obj_driver_dither.setEnabled(False)
  465. print("JackSettings::loadDriverSettings() - Invalid dither value '%s'" % value)
  466. elif attribute == "inchannels":
  467. self.obj_driver_inchannels.setValue(int(value))
  468. elif attribute == "outchannels":
  469. self.obj_driver_outchannels.setValue(int(value))
  470. elif attribute == "shorts":
  471. self.obj_driver_shorts.setChecked(bool(value))
  472. elif attribute == "input-latency":
  473. self.obj_driver_input_latency.setValue(int(value))
  474. elif attribute == "output-latency":
  475. self.obj_driver_output_latency.setValue(int(value))
  476. elif attribute in ("midi", "midi-driver"):
  477. value = str(value)
  478. if value == "none":
  479. self.obj_driver_midi_driver.setCurrentIndex(0)
  480. elif value == "seq":
  481. self.obj_driver_midi_driver.setCurrentIndex(1)
  482. elif value == "raw":
  483. self.obj_driver_midi_driver.setCurrentIndex(2)
  484. else:
  485. self.obj_driver_midi_driver.setEnabled(False)
  486. print("JackSettings::loadDriverSettings() - Invalid midi-driver value '%s'" % value)
  487. elif attribute == "wait":
  488. self.obj_driver_wait.setValue(int(value))
  489. elif attribute == "verbose":
  490. self.obj_driver_verbose.setValue(int(value))
  491. elif attribute == "snoop":
  492. self.obj_driver_snoop.setChecked(bool(value))
  493. elif attribute == "channels":
  494. self.obj_driver_channels.setValue(int(value))
  495. else:
  496. print("JackSettings::loadDriverSettings() - Unimplemented driver attribute '%s', value: '%s'" % (attribute, str(value)))
  497. # -------------------------------------------------------------
  498. # Helper functions
  499. def getAlsaDeviceList(self):
  500. alsa_dev_list = []
  501. aplay_out = getoutput("env LANG=C aplay -l").split("\n")
  502. for line in aplay_out:
  503. line = line.strip()
  504. if line.startswith("card "):
  505. card_info = line.split(", ", 1)[0].split(": ")
  506. card_index = card_info[0].replace("card ", "")
  507. card_name = card_info[1].split(" [")[0]
  508. device_info = line.split(", ", 1)[1].split(": ")
  509. device_index = device_info[0].replace("device ", "")
  510. device_name = device_info[1].split(" [")[0]
  511. if card_name != "Loopback":
  512. full_name = "hw:%s,%s [%s]" % (card_name, device_index, device_name)
  513. alsa_dev_list.append(full_name)
  514. return alsa_dev_list
  515. def setComboBoxValue(self, box, text, split=False):
  516. for i in range(box.count()):
  517. if box.itemText(i) == text or (box.itemText(i).split(" ")[0] == text and split):
  518. box.setCurrentIndex(i)
  519. break
  520. else:
  521. if text:
  522. box.addItem(text)
  523. box.setCurrentIndex(box.count() - 1)
  524. # -------------------------------------------------------------
  525. # Qt SLOT calls
  526. @pyqtSlot()
  527. def slot_checkALSASelection(self):
  528. if self.m_driver == "alsa":
  529. check = bool(self.obj_driver_duplex.isChecked() and (self.obj_driver_capture.currentIndex() > 0 or self.obj_driver_playback.currentIndex() > 0))
  530. self.obj_driver_device.setEnabled(not check)
  531. @pyqtSlot(bool)
  532. def slot_checkDuplexSelection(self, active):
  533. if driverHasFeature("duplex"):
  534. self.obj_driver_capture.setEnabled(active)
  535. self.obj_driver_capture_label.setEnabled(active)
  536. self.obj_driver_playback.setEnabled(active)
  537. self.obj_driver_playback_label.setEnabled(active)
  538. #self.obj_driver_inchannels.setEnabled(active)
  539. #self.obj_driver_inchannels_label.setEnabled(active)
  540. #self.obj_driver_input_latency.setEnabled(active)
  541. #self.obj_driver_input_latency_label.setEnabled(active)
  542. self.slot_checkALSASelection()
  543. @pyqtSlot(int)
  544. def slot_checkDriverSelection(self, row):
  545. # Save previous settings
  546. self.saveDriverSettings(False)
  547. # Set new Jack driver
  548. self.m_driver = dbus.String(self.obj_server_driver.item(row, 0).text().lower())
  549. jackctl.SetParameterValue(["engine", "driver"], self.m_driver)
  550. # Add device list
  551. self.obj_driver_device.clear()
  552. if driverHasFeature("device"):
  553. if LINUX and self.m_driver == "alsa":
  554. dev_list = self.getAlsaDeviceList()
  555. for dev in dev_list:
  556. self.obj_driver_device.addItem(dev)
  557. else:
  558. dev_list = jackctl.GetParameterConstraint(["driver", "device"])[3]
  559. for i in range(len(dev_list)):
  560. self.obj_driver_device.addItem(dev_list[i][0] + " [%s]" % str(dev_list[i][1]))
  561. # Custom 'playback' and 'capture' values
  562. self.obj_driver_capture.clear()
  563. self.obj_driver_playback.clear()
  564. if self.m_driver == "alsa":
  565. self.obj_driver_capture.addItem("none")
  566. self.obj_driver_playback.addItem("none")
  567. if LINUX:
  568. dev_list = self.getAlsaDeviceList()
  569. for dev in dev_list:
  570. self.obj_driver_capture.addItem(dev)
  571. self.obj_driver_playback.addItem(dev)
  572. else:
  573. dev_list = jackctl.GetParameterConstraint(["driver", "device"])[3]
  574. for i in range(len(dev_list)):
  575. self.obj_driver_capture.addItem(dev_list[i][0] + " [" + dev_list[i][1] + "]")
  576. self.obj_driver_playback.addItem(dev_list[i][0] + " [" + dev_list[i][1] + "]")
  577. elif self.m_driver == "dummy":
  578. for i in range(16):
  579. self.obj_driver_capture.addItem("%i" % int((i * 2) + 2))
  580. self.obj_driver_playback.addItem("%i" % int((i * 2) + 2))
  581. elif self.m_driver == "firewire":
  582. self.obj_driver_capture.addItem("no")
  583. self.obj_driver_capture.addItem("yes")
  584. self.obj_driver_playback.addItem("no")
  585. self.obj_driver_playback.addItem("yes")
  586. elif driverHasFeature("playback") or driverHasFeature("capture"):
  587. print("JackSettings::slot_checkDriverSelection() - Custom playback/capture for driver '%s' not implemented yet" % self.m_driver)
  588. # Load Driver Settings
  589. self.loadDriverSettings()
  590. # Enable widgets according to driver
  591. self.obj_driver_capture.setEnabled(driverHasFeature("capture"))
  592. self.obj_driver_capture_label.setEnabled(driverHasFeature("capture"))
  593. self.obj_driver_playback.setEnabled(driverHasFeature("playback"))
  594. self.obj_driver_playback_label.setEnabled(driverHasFeature("playback"))
  595. self.obj_driver_device.setEnabled(driverHasFeature("device"))
  596. self.obj_driver_device_label.setEnabled(driverHasFeature("device"))
  597. self.obj_driver_rate.setEnabled(driverHasFeature("rate"))
  598. self.obj_driver_rate_label.setEnabled(driverHasFeature("rate"))
  599. self.obj_driver_period.setEnabled(driverHasFeature("period"))
  600. self.obj_driver_period_label.setEnabled(driverHasFeature("period"))
  601. self.obj_driver_nperiods.setEnabled(driverHasFeature("nperiods"))
  602. self.obj_driver_nperiods_label.setEnabled(driverHasFeature("nperiods"))
  603. self.obj_driver_hwmon.setEnabled(driverHasFeature("hwmon"))
  604. self.obj_driver_hwmeter.setEnabled(driverHasFeature("hwmeter"))
  605. self.obj_driver_duplex.setEnabled(driverHasFeature("duplex"))
  606. self.obj_driver_softmode.setEnabled(driverHasFeature("softmode"))
  607. self.obj_driver_monitor.setEnabled(driverHasFeature("monitor"))
  608. self.obj_driver_dither.setEnabled(driverHasFeature("dither"))
  609. self.obj_driver_dither_label.setEnabled(driverHasFeature("dither"))
  610. self.obj_driver_inchannels.setEnabled(driverHasFeature("inchannels"))
  611. self.obj_driver_inchannels_label.setEnabled(driverHasFeature("inchannels"))
  612. self.obj_driver_outchannels.setEnabled(driverHasFeature("outchannels"))
  613. self.obj_driver_outchannels_label.setEnabled(driverHasFeature("outchannels"))
  614. self.obj_driver_shorts.setEnabled(driverHasFeature("shorts"))
  615. self.obj_driver_input_latency.setEnabled(driverHasFeature("input-latency"))
  616. self.obj_driver_input_latency_label.setEnabled(driverHasFeature("input-latency"))
  617. self.obj_driver_output_latency.setEnabled(driverHasFeature("output-latency"))
  618. self.obj_driver_output_latency_label.setEnabled(driverHasFeature("output-latency"))
  619. self.obj_driver_midi_driver.setEnabled(driverHasFeature("midi") or driverHasFeature("midi-driver"))
  620. self.obj_driver_midi_driver_label.setEnabled(driverHasFeature("midi") or driverHasFeature("midi-driver"))
  621. self.obj_driver_wait.setEnabled(driverHasFeature("wait"))
  622. self.obj_driver_wait_label.setEnabled(driverHasFeature("wait"))
  623. self.obj_driver_verbose.setEnabled(driverHasFeature("verbose"))
  624. self.obj_driver_verbose_label.setEnabled(driverHasFeature("verbose"))
  625. self.obj_driver_snoop.setEnabled(driverHasFeature("snoop"))
  626. self.obj_driver_channels.setEnabled(driverHasFeature("channels"))
  627. self.obj_driver_channels_label.setEnabled(driverHasFeature("channels"))
  628. # Misc stuff
  629. if self.obj_server_driver.item(0, row).text() == "ALSA":
  630. self.toolbox_driver_misc.setCurrentIndex(1)
  631. self.obj_driver_capture_label.setText(self.tr("Input Device:"))
  632. self.obj_driver_playback_label.setText(self.tr("Output Device:"))
  633. elif self.obj_server_driver.item(0, row).text() == "Dummy":
  634. self.toolbox_driver_misc.setCurrentIndex(2)
  635. self.obj_driver_capture_label.setText(self.tr("Input Ports:"))
  636. self.obj_driver_playback_label.setText(self.tr("Output Ports:"))
  637. elif self.obj_server_driver.item(0, row).text() == "FireWire":
  638. self.toolbox_driver_misc.setCurrentIndex(3)
  639. self.obj_driver_capture_label.setText(self.tr("Capture Ports:"))
  640. self.obj_driver_playback_label.setText(self.tr("Playback Ports:"))
  641. elif self.obj_server_driver.item(0, row).text() == "Loopback":
  642. self.toolbox_driver_misc.setCurrentIndex(4)
  643. else:
  644. self.toolbox_driver_misc.setCurrentIndex(0)
  645. self.slot_checkDuplexSelection(self.obj_driver_duplex.isChecked())
  646. @pyqtSlot()
  647. def slot_saveJackSettings(self):
  648. self.saveServerSettings()
  649. self.saveDriverSettings(True)
  650. @pyqtSlot()
  651. def slot_resetJackSettings(self):
  652. if self.tabWidget.currentIndex() == 0:
  653. self.loadServerSettings(True, True)
  654. elif self.tabWidget.currentIndex() == 1:
  655. self.loadDriverSettings(True, True)
  656. @pyqtSlot()
  657. def slot_closeWithError(self):
  658. QMessageBox.critical(self, self.tr("Error"), self.tr("jackdbus is not available!\nIt's not possible to configure JACK at this point."))
  659. self.close()
  660. def done(self, r):
  661. QDialog.done(self, r)
  662. self.close()
  663. # -------------------------------------------------------------
  664. # Allow to use this as a standalone app
  665. if __name__ == '__main__':
  666. # Additional imports
  667. import resources_rc
  668. from sys import argv as sys_argv, exit as sys_exit
  669. from PyQt4.QtGui import QApplication, QIcon
  670. # App initialization
  671. app = QApplication(sys_argv)
  672. # Connect to DBus
  673. if dbus:
  674. if initBus(dbus.SessionBus()):
  675. QMessageBox.critical(None, app.translate("JackSettingsW", "Error"), app.translate("JackSettingsW",
  676. "jackdbus is not available!\n"
  677. "Is not possible to configure JACK at this point."))
  678. sys_exit(1)
  679. else:
  680. QMessageBox.critical(None, app.translate("JackSettingsW", "Error"),
  681. app.translate("JackSettingsW", "DBus is not available, cannot continue."))
  682. sys_exit(1)
  683. # Show GUI
  684. gui = JackSettingsW(None)
  685. gui.setWindowIcon(QIcon(":/scalable/jack.svg"))
  686. gui.show()
  687. # App-Loop
  688. sys_exit(app.exec_())