|
|
@@ -0,0 +1,761 @@ |
|
|
|
#!/usr/bin/env python3 |
|
|
|
# -*- coding: utf-8 -*- |
|
|
|
|
|
|
|
# JACK Settings Dialog |
|
|
|
# Copyright (C) 2012 Filipe Coelho <falktx@gmail.com> |
|
|
|
# |
|
|
|
# This program is free software; you can redistribute it and/or modify |
|
|
|
# it under the terms of the GNU General Public License as published by |
|
|
|
# the Free Software Foundation; either version 2 of the License, or |
|
|
|
# any later version. |
|
|
|
# |
|
|
|
# This program is distributed in the hope that it will be useful, |
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
# GNU General Public License for more details. |
|
|
|
# |
|
|
|
# For a full copy of the GNU General Public License see the COPYING file |
|
|
|
|
|
|
|
# Imports (Global) |
|
|
|
from PyQt4.QtCore import pyqtSlot, Qt, QTimer, SIGNAL, SLOT |
|
|
|
from PyQt4.QtGui import QDialog, QDialogButtonBox, QMessageBox |
|
|
|
from sys import platform |
|
|
|
|
|
|
|
# Imports (Custom Stuff) |
|
|
|
import ui_settings_jack |
|
|
|
|
|
|
|
# Imports (DBus) |
|
|
|
try: |
|
|
|
import dbus |
|
|
|
except: |
|
|
|
dbus = None |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
|
|
# global object |
|
|
|
global jackctl |
|
|
|
jackctl = None |
|
|
|
|
|
|
|
# enum jack_timer_type_t |
|
|
|
JACK_TIMER_SYSTEM_CLOCK = 0 |
|
|
|
JACK_TIMER_CYCLE_COUNTER = 1 |
|
|
|
JACK_TIMER_HPET = 2 |
|
|
|
|
|
|
|
# Set Platform |
|
|
|
if ("linux" in platform): |
|
|
|
LINUX = True |
|
|
|
else: |
|
|
|
LINUX = False |
|
|
|
|
|
|
|
# Init DBus |
|
|
|
def initBus(bus): |
|
|
|
global jackctl |
|
|
|
try: |
|
|
|
jackctl = dbus.Interface(bus.get_object("org.jackaudio.service", "/org/jackaudio/Controller"), "org.jackaudio.Configure") |
|
|
|
return 0 |
|
|
|
except: |
|
|
|
jackctl = None |
|
|
|
return 1 |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Helper functions |
|
|
|
|
|
|
|
def bool2str(yesno): |
|
|
|
return "True" if yesno else "False" |
|
|
|
|
|
|
|
def getBufferSize(): |
|
|
|
return getDriverParameter("period", -1) |
|
|
|
|
|
|
|
def getSampleRate(): |
|
|
|
return getDriverParameter("rate", -1) |
|
|
|
|
|
|
|
def isRealtime(): |
|
|
|
return getEngineParameter("realtime", False) |
|
|
|
|
|
|
|
def setBufferSize(bsize): |
|
|
|
return setDriverParameter("period", dbus.UInt32(bsize)) |
|
|
|
|
|
|
|
def setSampleRate(srate): |
|
|
|
return setDriverParameter("rate", dbus.UInt32(srate)) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Helper functions (engine) |
|
|
|
|
|
|
|
def engineHasFeature(feature): |
|
|
|
feature_list = jackctl.ReadContainer(["engine"])[1] |
|
|
|
return bool(dbus.String(feature) in feature_list) |
|
|
|
|
|
|
|
def getEngineParameter(parameter, error): |
|
|
|
if (engineHasFeature(parameter) == False): |
|
|
|
return error |
|
|
|
else: |
|
|
|
return jackctl.GetParameterValue(["engine",parameter])[2] |
|
|
|
|
|
|
|
def setEngineParameter(parameter, value, optional=True): |
|
|
|
if (engineHasFeature(parameter) == False): |
|
|
|
return False |
|
|
|
elif (optional): |
|
|
|
if (value != jackctl.GetParameterValue(["engine",parameter])[2]): |
|
|
|
return bool(jackctl.SetParameterValue(["engine",parameter],value)) |
|
|
|
else: |
|
|
|
return False |
|
|
|
else: |
|
|
|
return bool(jackctl.SetParameterValue(["engine",parameter],value)) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Helper functions (driver) |
|
|
|
|
|
|
|
def driverHasFeature(feature): |
|
|
|
feature_list = jackctl.ReadContainer(["driver"])[1] |
|
|
|
return bool(dbus.String(feature) in feature_list) |
|
|
|
|
|
|
|
def getDriverParameter(parameter, error): |
|
|
|
if (driverHasFeature(parameter) == False): |
|
|
|
return error |
|
|
|
else: |
|
|
|
return jackctl.GetParameterValue(["driver",parameter])[2] |
|
|
|
|
|
|
|
def setDriverParameter(parameter, value, optional=True): |
|
|
|
if (driverHasFeature(parameter) == False): |
|
|
|
return False |
|
|
|
elif (optional): |
|
|
|
if (value != jackctl.GetParameterValue(["driver",parameter])[2]): |
|
|
|
return bool(jackctl.SetParameterValue(["driver",parameter],value)) |
|
|
|
else: |
|
|
|
return False |
|
|
|
else: |
|
|
|
return bool(jackctl.SetParameterValue(["driver",parameter],value)) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# JACK Settings Dialog |
|
|
|
|
|
|
|
class JackSettingsW(QDialog, ui_settings_jack.Ui_JackSettingsW): |
|
|
|
def __init__(self, parent): |
|
|
|
QDialog.__init__(self, parent) |
|
|
|
self.setupUi(self) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Check if we've got valid control interface |
|
|
|
|
|
|
|
if not jackctl: |
|
|
|
QTimer.singleShot(0, self, SLOT("slot_closeWithError()")) |
|
|
|
return |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Align driver text and hide non available ones |
|
|
|
|
|
|
|
driver_list = jackctl.ReadContainer(["drivers"])[1] |
|
|
|
for i in range(self.obj_server_driver.rowCount()): |
|
|
|
self.obj_server_driver.item(0, i).setTextAlignment(Qt.AlignCenter) |
|
|
|
if (dbus.String(self.obj_server_driver.item(0, i).text().lower()) not in driver_list): |
|
|
|
self.obj_server_driver.hideRow(i) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Set-up connections |
|
|
|
|
|
|
|
self.connect(self, SIGNAL("accepted()"), SLOT("slot_saveJackSettings()")) |
|
|
|
self.connect(self.buttonBox.button(QDialogButtonBox.Reset), SIGNAL("clicked()"), SLOT("slot_resetJackSettings()")) |
|
|
|
|
|
|
|
self.connect(self.obj_driver_duplex, SIGNAL("clicked(bool)"), SLOT("slot_checkDuplexSelection(bool)")) |
|
|
|
self.connect(self.obj_server_driver, SIGNAL("currentCellChanged(int, int, int, int)"), SLOT("slot_checkDriverSelection(int, int, int, int)")) |
|
|
|
|
|
|
|
self.connect(self.obj_driver_capture, SIGNAL("currentIndexChanged(int)"), SLOT("slot_checkALSASelection()")) |
|
|
|
self.connect(self.obj_driver_playback, SIGNAL("currentIndexChanged(int)"), SLOT("slot_checkALSASelection()")) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Load initial settings |
|
|
|
|
|
|
|
self.m_driver = "" |
|
|
|
self.m_server_clock_source_broken = False |
|
|
|
|
|
|
|
self.checkEngine() |
|
|
|
self.loadServerSettings() |
|
|
|
self.loadDriverSettings(True) # reset because we'll change it below |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Load selected JACK driver |
|
|
|
|
|
|
|
self.m_driver = str(jackctl.GetParameterValue(["engine","driver"])[2]) |
|
|
|
for i in range(self.obj_server_driver.rowCount()): |
|
|
|
if (self.obj_server_driver.item(i, 0).text().lower() == self.m_driver): |
|
|
|
self.obj_server_driver.setCurrentCell(i, 0) |
|
|
|
break |
|
|
|
|
|
|
|
# Special ALSA check |
|
|
|
self.slot_checkALSASelection() |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Engine calls |
|
|
|
|
|
|
|
def checkEngine(self): |
|
|
|
self.obj_server_name.setEnabled(engineHasFeature("name")) |
|
|
|
self.obj_server_realtime.setEnabled(engineHasFeature("realtime")) |
|
|
|
self.obj_server_realtime_priority.setEnabled(engineHasFeature("realtime-priority")) |
|
|
|
self.obj_server_temporary.setEnabled(engineHasFeature("temporary")) |
|
|
|
self.obj_server_verbose.setEnabled(engineHasFeature("verbose")) |
|
|
|
self.obj_server_client_timeout.setEnabled(engineHasFeature("client-timeout")) |
|
|
|
self.obj_server_clock_source.setEnabled(engineHasFeature("clock-source")) |
|
|
|
self.obj_server_port_max.setEnabled(engineHasFeature("port-max")) |
|
|
|
self.obj_server_replace_registry.setEnabled(engineHasFeature("replace-registry")) |
|
|
|
self.obj_server_sync.setEnabled(engineHasFeature("sync")) |
|
|
|
self.obj_server_self_connect_mode.setEnabled(engineHasFeature("self-connect-mode")) |
|
|
|
|
|
|
|
# Disable clock-source if not on Linux |
|
|
|
if (LINUX == False): |
|
|
|
self.obj_server_clock_source.setEnabled(False) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Server calls |
|
|
|
|
|
|
|
def saveServerSettings(self): |
|
|
|
if (self.obj_server_name.isEnabled()): |
|
|
|
value = dbus.String(self.obj_server_name.text()) |
|
|
|
setEngineParameter("name", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_realtime.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_server_realtime.isChecked()) |
|
|
|
setEngineParameter("realtime", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_realtime_priority.isEnabled()): |
|
|
|
value = dbus.Int32(self.obj_server_realtime_priority.value()) |
|
|
|
setEngineParameter("realtime-priority", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_temporary.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_server_temporary.isChecked()) |
|
|
|
setEngineParameter("temporary", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_verbose.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_server_verbose.isChecked()) |
|
|
|
setEngineParameter("verbose", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_client_timeout.isEnabled()): |
|
|
|
value = dbus.Int32(int(self.obj_server_client_timeout.currentText())) |
|
|
|
setEngineParameter("client-timeout", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_clock_source.isEnabled() or 1): |
|
|
|
value = None |
|
|
|
if (self.obj_server_clock_source_system.isChecked()): |
|
|
|
if (self.m_server_clock_source_broken): |
|
|
|
value = dbus.UInt32(JACK_TIMER_SYSTEM_CLOCK) |
|
|
|
else: |
|
|
|
value = dbus.Byte("s".encode("ascii")) |
|
|
|
elif (self.obj_server_clock_source_cycle.isChecked()): |
|
|
|
if (self.m_server_clock_source_broken): |
|
|
|
value = dbus.UInt32(JACK_TIMER_CYCLE_COUNTER) |
|
|
|
else: |
|
|
|
value = dbus.Byte("c".encode("ascii")) |
|
|
|
elif (self.obj_server_clock_source_hpet.isChecked()): |
|
|
|
if (self.m_server_clock_source_broken): |
|
|
|
value = dbus.UInt32(JACK_TIMER_HPET) |
|
|
|
else: |
|
|
|
value = dbus.Byte("h".encode("ascii")) |
|
|
|
else: |
|
|
|
value = None |
|
|
|
print("JackSettings::saveServerSettings() - Cannot save clock-source value") |
|
|
|
|
|
|
|
if (value != None): |
|
|
|
setEngineParameter("clock-source", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_port_max.isEnabled()): |
|
|
|
value = dbus.UInt32(int(self.obj_server_port_max.currentText())) |
|
|
|
setEngineParameter("port-max", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_replace_registry.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_server_replace_registry.isChecked()) |
|
|
|
setEngineParameter("replace-registry", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_sync.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_server_sync.isChecked()) |
|
|
|
setEngineParameter("sync", value, True) |
|
|
|
|
|
|
|
if (self.obj_server_self_connect_mode.isEnabled()): |
|
|
|
if (self.obj_server_self_connect_mode_0.isChecked()): |
|
|
|
value = dbus.Byte(" ".encode("ascii")) |
|
|
|
elif (self.obj_server_self_connect_mode_1.isChecked()): |
|
|
|
value = dbus.Byte("E".encode("ascii")) |
|
|
|
elif (self.obj_server_self_connect_mode_2.isChecked()): |
|
|
|
value = dbus.Byte("e".encode("ascii")) |
|
|
|
elif (self.obj_server_self_connect_mode_3.isChecked()): |
|
|
|
value = dbus.Byte("A".encode("ascii")) |
|
|
|
elif (self.obj_server_self_connect_mode_4.isChecked()): |
|
|
|
value = dbus.Byte("a".encode("ascii")) |
|
|
|
else: |
|
|
|
value = None |
|
|
|
print("JackSettings::saveServerSettings() - Cannot save self-connect-mode value") |
|
|
|
|
|
|
|
if (value != None): |
|
|
|
setEngineParameter("self-connect-mode", value, True) |
|
|
|
|
|
|
|
def loadServerSettings(self, reset=False, forceReset=False): |
|
|
|
settings = jackctl.ReadContainer(["engine"]) |
|
|
|
|
|
|
|
for i in range(len(settings[1])): |
|
|
|
attribute = str(settings[1][i]) |
|
|
|
if (reset): |
|
|
|
value = jackctl.GetParameterValue(["engine",attribute])[1] |
|
|
|
if (forceReset and attribute != "driver"): |
|
|
|
jackctl.ResetParameterValue(["engine",attribute]) |
|
|
|
else: |
|
|
|
value = jackctl.GetParameterValue(["engine",attribute])[2] |
|
|
|
|
|
|
|
if (attribute == "name"): |
|
|
|
self.obj_server_name.setText(str(value)) |
|
|
|
elif (attribute == "realtime"): |
|
|
|
self.obj_server_realtime.setChecked(bool(value)) |
|
|
|
elif (attribute == "realtime-priority"): |
|
|
|
self.obj_server_realtime_priority.setValue(int(value)) |
|
|
|
elif (attribute == "temporary"): |
|
|
|
self.obj_server_temporary.setChecked(bool(value)) |
|
|
|
elif (attribute == "verbose"): |
|
|
|
self.obj_server_verbose.setChecked(bool(value)) |
|
|
|
elif (attribute == "client-timeout"): |
|
|
|
self.setComboBoxValue(self.obj_server_client_timeout, str(value)) |
|
|
|
elif (attribute == "clock-source"): |
|
|
|
value = str(value) |
|
|
|
if (value == "c"): |
|
|
|
self.obj_server_clock_source_cycle.setChecked(True) |
|
|
|
elif (value == "h"): |
|
|
|
self.obj_server_clock_source_hpet.setChecked(True) |
|
|
|
elif (value == "s"): |
|
|
|
self.obj_server_clock_source_system.setChecked(True) |
|
|
|
else: |
|
|
|
self.m_server_clock_source_broken = True |
|
|
|
if (value == str(JACK_TIMER_SYSTEM_CLOCK)): |
|
|
|
self.obj_server_clock_source_system.setChecked(True) |
|
|
|
elif (value == str(JACK_TIMER_CYCLE_COUNTER)): |
|
|
|
self.obj_server_clock_source_cycle.setChecked(True) |
|
|
|
elif (value == str(JACK_TIMER_HPET)): |
|
|
|
self.obj_server_clock_source_hpet.setChecked(True) |
|
|
|
else: |
|
|
|
self.obj_server_clock_source.setEnabled(False) |
|
|
|
print("JackSettings::saveServerSettings() - Invalid clock-source value '%s'" % (value)) |
|
|
|
elif (attribute == "port-max"): |
|
|
|
self.setComboBoxValue(self.obj_server_port_max, str(value)) |
|
|
|
elif (attribute == "replace-registry"): |
|
|
|
self.obj_server_replace_registry.setChecked(bool(value)) |
|
|
|
elif (attribute == "sync"): |
|
|
|
self.obj_server_sync.setChecked(bool(value)) |
|
|
|
elif (attribute == "self-connect-mode"): |
|
|
|
value = str(value) |
|
|
|
if (value == " "): |
|
|
|
self.obj_server_self_connect_mode_0.setChecked(True) |
|
|
|
elif (value == "E"): |
|
|
|
self.obj_server_self_connect_mode_1.setChecked(True) |
|
|
|
elif (value == "e"): |
|
|
|
self.obj_server_self_connect_mode_2.setChecked(True) |
|
|
|
elif (value == "A"): |
|
|
|
self.obj_server_self_connect_mode_3.setChecked(True) |
|
|
|
elif (value == "a"): |
|
|
|
self.obj_server_self_connect_mode_4.setChecked(True) |
|
|
|
else: |
|
|
|
self.obj_server_self_connect_mode.setEnabled(False) |
|
|
|
print("JackSettings::loadServerSettings() - Invalid self-connect-mode value '%s'" % (value)) |
|
|
|
elif (attribute in ("driver", "slave-drivers")): |
|
|
|
pass |
|
|
|
else: |
|
|
|
print("JackSettings::loadServerSettings() - Unimplemented server attribute '%s', value: '%s'" % (attribute, str(value))) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Driver calls |
|
|
|
|
|
|
|
def saveDriverSettings(self): |
|
|
|
if (self.obj_driver_device.isEnabled()): |
|
|
|
value = dbus.String(self.obj_driver_device.currentText().split(" ")[0]) |
|
|
|
if (value != jackctl.GetParameterValue(["driver", "device"])[2]): |
|
|
|
jackctl.SetParameterValue(["driver", "device"], value) |
|
|
|
|
|
|
|
if (self.obj_driver_capture.isEnabled()): |
|
|
|
if (self.m_driver == "alsa"): |
|
|
|
value = dbus.String(self.obj_driver_capture.currentText().split(" ")[0]) |
|
|
|
elif (self.m_driver == "dummy"): |
|
|
|
value = dbus.UInt32(int(self.obj_driver_capture.currentText())) |
|
|
|
elif (self.m_driver == "firewire"): |
|
|
|
value = dbus.Boolean(self.obj_driver_capture.currentIndex() == 1) |
|
|
|
else: |
|
|
|
value = None |
|
|
|
print("JackSettings::saveDriverSettings() - Cannot save capture value") |
|
|
|
|
|
|
|
if (value != None): |
|
|
|
setDriverParameter("capture", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_playback.isEnabled()): |
|
|
|
if (self.m_driver == "alsa"): |
|
|
|
value = dbus.String(self.obj_driver_playback.currentText().split(" ")[0]) |
|
|
|
elif (self.m_driver == "dummy"): |
|
|
|
value = dbus.UInt32(int(self.obj_driver_playback.currentText())) |
|
|
|
elif (self.m_driver == "firewire"): |
|
|
|
value = dbus.Boolean(self.obj_driver_playback.currentIndex() == 1) |
|
|
|
else: |
|
|
|
value = None |
|
|
|
print("JackSettings::saveDriverSettings() - Cannot save playback value") |
|
|
|
|
|
|
|
if (value != None): |
|
|
|
setDriverParameter("playback", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_rate.isEnabled()): |
|
|
|
value = dbus.UInt32(int(self.obj_driver_rate.currentText())) |
|
|
|
setDriverParameter("rate", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_period.isEnabled()): |
|
|
|
value = dbus.UInt32(int(self.obj_driver_period.currentText())) |
|
|
|
setDriverParameter("period", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_nperiods.isEnabled()): |
|
|
|
value = dbus.UInt32(self.obj_driver_nperiods.value()) |
|
|
|
setDriverParameter("nperiods", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_hwmon.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_driver_hwmon.isChecked()) |
|
|
|
setDriverParameter("hwmon", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_hwmeter.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_driver_hwmeter.isChecked()) |
|
|
|
setDriverParameter("hwmeter", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_duplex.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_driver_duplex.isChecked()) |
|
|
|
setDriverParameter("duplex", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_softmode.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_driver_softmode.isChecked()) |
|
|
|
setDriverParameter("softmode", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_monitor.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_driver_monitor.isChecked()) |
|
|
|
setDriverParameter("monitor", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_dither.isEnabled()): |
|
|
|
if (self.obj_driver_dither.currentIndex() == 0): |
|
|
|
value = dbus.Byte("n".encode("ascii")) |
|
|
|
elif (self.obj_driver_dither.currentIndex() == 1): |
|
|
|
value = dbus.Byte("r".encode("ascii")) |
|
|
|
elif (self.obj_driver_dither.currentIndex() == 2): |
|
|
|
value = dbus.Byte("s".encode("ascii")) |
|
|
|
elif (self.obj_driver_dither.currentIndex() == 3): |
|
|
|
value = dbus.Byte("t".encode("ascii")) |
|
|
|
else: |
|
|
|
value = None |
|
|
|
print("JackSettings::saveDriverSettings() - Cannot save dither value") |
|
|
|
|
|
|
|
if (value != None): |
|
|
|
setDriverParameter("dither", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_inchannels.isEnabled()): |
|
|
|
value = dbus.UInt32(self.obj_driver_inchannels.value()) |
|
|
|
setDriverParameter("inchannels", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_outchannels.isEnabled()): |
|
|
|
value = dbus.UInt32(self.obj_driver_outchannels.value()) |
|
|
|
setDriverParameter("outchannels", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_shorts.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_driver_shorts.isChecked()) |
|
|
|
setDriverParameter("shorts", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_input_latency.isEnabled()): |
|
|
|
value = dbus.UInt32(self.obj_driver_input_latency.value()) |
|
|
|
setDriverParameter("input-latency", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_output_latency.isEnabled()): |
|
|
|
value = dbus.UInt32(self.obj_driver_output_latency.value()) |
|
|
|
setDriverParameter("output-latency", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_midi_driver.isEnabled()): |
|
|
|
if (self.obj_driver_midi_driver.currentIndex() == 0): |
|
|
|
value = dbus.String("none") |
|
|
|
elif (self.obj_driver_midi_driver.currentIndex() == 1): |
|
|
|
value = dbus.String("seq") |
|
|
|
elif (self.obj_driver_midi_driver.currentIndex() == 2): |
|
|
|
value = dbus.String("raw") |
|
|
|
else: |
|
|
|
value = None |
|
|
|
print("JackSettings::saveDriverSettings() - Cannot save midi-driver value") |
|
|
|
|
|
|
|
if (value != None): |
|
|
|
setDriverParameter("midi-driver", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_wait.isEnabled()): |
|
|
|
value = dbus.UInt32(self.obj_driver_wait.value()) |
|
|
|
setDriverParameter("wait", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_verbose.isEnabled()): |
|
|
|
value = dbus.UInt32(self.obj_driver_verbose.value()) |
|
|
|
setDriverParameter("verbose", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_snoop.isEnabled()): |
|
|
|
value = dbus.Boolean(self.obj_driver_snoop.isChecked()) |
|
|
|
setDriverParameter("snoop", value, True) |
|
|
|
|
|
|
|
if (self.obj_driver_channels.isEnabled()): |
|
|
|
value = dbus.UInt32(self.obj_driver_channels.value()) |
|
|
|
setDriverParameter("channels", value, True) |
|
|
|
|
|
|
|
def loadDriverSettings(self, reset=False, forceReset=False): |
|
|
|
settings = jackctl.ReadContainer(["driver"]) |
|
|
|
|
|
|
|
for i in range(len(settings[1])): |
|
|
|
attribute = str(settings[1][i]) |
|
|
|
if (reset): |
|
|
|
value = jackctl.GetParameterValue(["driver",attribute])[1] |
|
|
|
if (forceReset): |
|
|
|
jackctl.ResetParameterValue(["driver",attribute]) |
|
|
|
else: |
|
|
|
value = jackctl.GetParameterValue(["driver",attribute])[2] |
|
|
|
|
|
|
|
if (attribute == "device"): |
|
|
|
self.setComboBoxValue(self.obj_driver_device, str(value), True) |
|
|
|
elif (attribute == "capture"): |
|
|
|
if (self.m_driver == "firewire"): |
|
|
|
self.obj_driver_capture.setCurrentIndex(1 if bool(value) else 0) |
|
|
|
else: |
|
|
|
self.setComboBoxValue(self.obj_driver_capture, str(value), True) |
|
|
|
elif (attribute == "playback"): |
|
|
|
if (self.m_driver == "firewire"): |
|
|
|
self.obj_driver_playback.setCurrentIndex(1 if bool(value) else 0) |
|
|
|
else: |
|
|
|
self.setComboBoxValue(self.obj_driver_playback, str(value), True) |
|
|
|
elif (attribute == "rate"): |
|
|
|
self.setComboBoxValue(self.obj_driver_rate, str(value)) |
|
|
|
elif (attribute == "period"): |
|
|
|
self.setComboBoxValue(self.obj_driver_period, str(value)) |
|
|
|
elif (attribute == "nperiods"): |
|
|
|
self.obj_driver_nperiods.setValue(int(value)) |
|
|
|
elif (attribute == "hwmon"): |
|
|
|
self.obj_driver_hwmon.setChecked(bool(value)) |
|
|
|
elif (attribute == "hwmeter"): |
|
|
|
self.obj_driver_hwmeter.setChecked(bool(value)) |
|
|
|
elif (attribute == "duplex"): |
|
|
|
self.obj_driver_duplex.setChecked(bool(value)) |
|
|
|
elif (attribute == "softmode"): |
|
|
|
self.obj_driver_softmode.setChecked(bool(value)) |
|
|
|
elif (attribute == "monitor"): |
|
|
|
self.obj_driver_monitor.setChecked(bool(value)) |
|
|
|
elif (attribute == "dither"): |
|
|
|
value = str(value) |
|
|
|
if (value == "n"): |
|
|
|
self.obj_driver_dither.setCurrentIndex(0) |
|
|
|
elif (value == "r"): |
|
|
|
self.obj_driver_dither.setCurrentIndex(1) |
|
|
|
elif (value == "s"): |
|
|
|
self.obj_driver_dither.setCurrentIndex(2) |
|
|
|
elif (value == "t"): |
|
|
|
self.obj_driver_dither.setCurrentIndex(3) |
|
|
|
else: |
|
|
|
self.obj_driver_dither.setEnabled(False) |
|
|
|
print("JackSettings::loadDriverSettings() - Invalid dither value '%s'" % (value)) |
|
|
|
elif (attribute == "inchannels"): |
|
|
|
self.obj_driver_inchannels.setValue(int(value)) |
|
|
|
elif (attribute == "outchannels"): |
|
|
|
self.obj_driver_outchannels.setValue(int(value)) |
|
|
|
elif (attribute == "shorts"): |
|
|
|
self.obj_driver_shorts.setChecked(bool(value)) |
|
|
|
elif (attribute == "input-latency"): |
|
|
|
self.obj_driver_input_latency.setValue(int(value)) |
|
|
|
elif (attribute == "output-latency"): |
|
|
|
self.obj_driver_output_latency.setValue(int(value)) |
|
|
|
elif (attribute == "midi-driver"): |
|
|
|
value = str(value) |
|
|
|
if (value == "none"): |
|
|
|
self.obj_driver_midi_driver.setCurrentIndex(0) |
|
|
|
elif (value == "seq"): |
|
|
|
self.obj_driver_midi_driver.setCurrentIndex(1) |
|
|
|
elif (value == "raw"): |
|
|
|
self.obj_driver_midi_driver.setCurrentIndex(2) |
|
|
|
else: |
|
|
|
self.obj_driver_midi_driver.setEnabled(False) |
|
|
|
print("JackSettings::loadDriverSettings() - Invalid midi-driver value '%s'" % (value)) |
|
|
|
elif (attribute == "wait"): |
|
|
|
self.obj_driver_wait.setValue(int(value)) |
|
|
|
elif (attribute == "verbose"): |
|
|
|
self.obj_driver_verbose.setValue(int(value)) |
|
|
|
elif (attribute == "snoop"): |
|
|
|
self.obj_driver_snoop.setChecked(bool(value)) |
|
|
|
elif (attribute == "channels"): |
|
|
|
self.obj_driver_channels.setValue(int(value)) |
|
|
|
else: |
|
|
|
print("JackSettings::loadDriverSettings() - Unimplemented driver attribute '%s', value: '%s'" % (attribute, str(value))) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Helper functions |
|
|
|
|
|
|
|
def setComboBoxValue(self, box, text, split=False): |
|
|
|
for i in range(box.count()): |
|
|
|
if (box.itemText(i) == text or (box.itemText(i).split(" ")[0] == text and split)): |
|
|
|
box.setCurrentIndex(i) |
|
|
|
break |
|
|
|
else: |
|
|
|
if (text): |
|
|
|
box.addItem(text) |
|
|
|
box.setCurrentIndex(box.count()-1) |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Qt SLOT calls |
|
|
|
|
|
|
|
@pyqtSlot() |
|
|
|
def slot_checkALSASelection(self): |
|
|
|
if (self.m_driver == "alsa"): |
|
|
|
check = (self.obj_driver_duplex.isChecked() and self.obj_driver_capture.currentIndex() > 0 and self.obj_driver_playback.currentIndex() > 0) |
|
|
|
self.obj_driver_device.setEnabled(not check) |
|
|
|
|
|
|
|
@pyqtSlot(bool) |
|
|
|
def slot_checkDuplexSelection(self, active): |
|
|
|
if (driverHasFeature("duplex")): |
|
|
|
self.obj_driver_capture.setEnabled(active) |
|
|
|
self.obj_driver_capture_label.setEnabled(active) |
|
|
|
#self.obj_driver_playback.setEnabled(active) |
|
|
|
#self.obj_driver_playback_label.setEnabled(active) |
|
|
|
self.obj_driver_inchannels.setEnabled(active) |
|
|
|
self.obj_driver_inchannels_label.setEnabled(active) |
|
|
|
self.obj_driver_input_latency.setEnabled(active) |
|
|
|
self.obj_driver_input_latency_label.setEnabled(active) |
|
|
|
|
|
|
|
self.slot_checkALSASelection() |
|
|
|
|
|
|
|
@pyqtSlot(int, int, int, int) |
|
|
|
def slot_checkDriverSelection(self, row, column, prev_row, prev_column): |
|
|
|
# Save previous settings |
|
|
|
self.saveDriverSettings() |
|
|
|
|
|
|
|
# Set new Jack driver |
|
|
|
self.m_driver = dbus.String(self.obj_server_driver.item(row, 0).text().lower()) |
|
|
|
jackctl.SetParameterValue(["engine","driver"],self.m_driver) |
|
|
|
|
|
|
|
# Add device list |
|
|
|
self.obj_driver_device.clear() |
|
|
|
if (driverHasFeature("device")): |
|
|
|
dev_list = jackctl.GetParameterConstraint(["driver","device"])[3] |
|
|
|
for i in range(len(dev_list)): |
|
|
|
self.obj_driver_device.addItem(dev_list[i][0]+" [%s]" % (str(dev_list[i][1]))) |
|
|
|
|
|
|
|
# Custom 'playback' and 'capture' values |
|
|
|
self.obj_driver_capture.clear() |
|
|
|
self.obj_driver_playback.clear() |
|
|
|
if (self.m_driver == "alsa"): |
|
|
|
self.obj_driver_capture.addItem("none") |
|
|
|
self.obj_driver_playback.addItem("none") |
|
|
|
dev_list = jackctl.GetParameterConstraint(["driver","device"])[3] |
|
|
|
for i in range(len(dev_list)): |
|
|
|
self.obj_driver_capture.addItem(dev_list[i][0]+" ["+dev_list[i][1]+"]") |
|
|
|
self.obj_driver_playback.addItem(dev_list[i][0]+" ["+dev_list[i][1]+"]") |
|
|
|
elif (self.m_driver == "dummy"): |
|
|
|
for i in range(16): |
|
|
|
self.obj_driver_capture.addItem("%i" % ((i*2)+2)) |
|
|
|
self.obj_driver_playback.addItem("%i" % ((i*2)+2)) |
|
|
|
elif (self.m_driver == "firewire"): |
|
|
|
self.obj_driver_capture.addItem("no") |
|
|
|
self.obj_driver_capture.addItem("yes") |
|
|
|
self.obj_driver_playback.addItem("no") |
|
|
|
self.obj_driver_playback.addItem("yes") |
|
|
|
elif (driverHasFeature("playback") or driverHasFeature("capture")): |
|
|
|
print("JackSettings::slot_checkDriverSelection() - Custom playback/capture for driver '%s' not implemented yet" % (self.m_driver)) |
|
|
|
|
|
|
|
# Load Driver Settings |
|
|
|
self.loadDriverSettings() |
|
|
|
|
|
|
|
# Enable widgets according to driver |
|
|
|
self.obj_driver_capture.setEnabled(driverHasFeature("capture")) |
|
|
|
self.obj_driver_capture_label.setEnabled(driverHasFeature("capture")) |
|
|
|
self.obj_driver_playback.setEnabled(driverHasFeature("playback")) |
|
|
|
self.obj_driver_playback_label.setEnabled(driverHasFeature("playback")) |
|
|
|
self.obj_driver_device.setEnabled(driverHasFeature("device")) |
|
|
|
self.obj_driver_device_label.setEnabled(driverHasFeature("device")) |
|
|
|
self.obj_driver_rate.setEnabled(driverHasFeature("rate")) |
|
|
|
self.obj_driver_rate_label.setEnabled(driverHasFeature("rate")) |
|
|
|
self.obj_driver_period.setEnabled(driverHasFeature("period")) |
|
|
|
self.obj_driver_period_label.setEnabled(driverHasFeature("period")) |
|
|
|
self.obj_driver_nperiods.setEnabled(driverHasFeature("nperiods")) |
|
|
|
self.obj_driver_nperiods_label.setEnabled(driverHasFeature("nperiods")) |
|
|
|
self.obj_driver_hwmon.setEnabled(driverHasFeature("hwmon")) |
|
|
|
self.obj_driver_hwmeter.setEnabled(driverHasFeature("hwmeter")) |
|
|
|
self.obj_driver_duplex.setEnabled(driverHasFeature("duplex")) |
|
|
|
self.obj_driver_softmode.setEnabled(driverHasFeature("softmode")) |
|
|
|
self.obj_driver_monitor.setEnabled(driverHasFeature("monitor")) |
|
|
|
self.obj_driver_dither.setEnabled(driverHasFeature("dither")) |
|
|
|
self.obj_driver_dither_label.setEnabled(driverHasFeature("dither")) |
|
|
|
self.obj_driver_inchannels.setEnabled(driverHasFeature("inchannels")) |
|
|
|
self.obj_driver_inchannels_label.setEnabled(driverHasFeature("inchannels")) |
|
|
|
self.obj_driver_outchannels.setEnabled(driverHasFeature("outchannels")) |
|
|
|
self.obj_driver_outchannels_label.setEnabled(driverHasFeature("outchannels")) |
|
|
|
self.obj_driver_shorts.setEnabled(driverHasFeature("shorts")) |
|
|
|
self.obj_driver_input_latency.setEnabled(driverHasFeature("input-latency")) |
|
|
|
self.obj_driver_input_latency_label.setEnabled(driverHasFeature("input-latency")) |
|
|
|
self.obj_driver_output_latency.setEnabled(driverHasFeature("output-latency")) |
|
|
|
self.obj_driver_output_latency_label.setEnabled(driverHasFeature("output-latency")) |
|
|
|
self.obj_driver_midi_driver.setEnabled(driverHasFeature("midi-driver")) |
|
|
|
self.obj_driver_midi_driver_label.setEnabled(driverHasFeature("midi-driver")) |
|
|
|
self.obj_driver_wait.setEnabled(driverHasFeature("wait")) |
|
|
|
self.obj_driver_wait_label.setEnabled(driverHasFeature("wait")) |
|
|
|
self.obj_driver_verbose.setEnabled(driverHasFeature("verbose")) |
|
|
|
self.obj_driver_verbose_label.setEnabled(driverHasFeature("verbose")) |
|
|
|
self.obj_driver_snoop.setEnabled(driverHasFeature("snoop")) |
|
|
|
self.obj_driver_channels.setEnabled(driverHasFeature("channels")) |
|
|
|
self.obj_driver_channels_label.setEnabled(driverHasFeature("channels")) |
|
|
|
|
|
|
|
# Misc stuff |
|
|
|
if (self.obj_server_driver.item(0, row).text() == "ALSA"): |
|
|
|
self.toolbox_driver_misc.setCurrentIndex(1) |
|
|
|
self.obj_driver_capture_label.setText(self.tr("Input Device:")) |
|
|
|
self.obj_driver_playback_label.setText(self.tr("Output Device:")) |
|
|
|
|
|
|
|
elif (self.obj_server_driver.item(0, row).text() == "Dummy"): |
|
|
|
self.toolbox_driver_misc.setCurrentIndex(2) |
|
|
|
self.obj_driver_capture_label.setText(self.tr("Input Ports:")) |
|
|
|
self.obj_driver_playback_label.setText(self.tr("Output Ports:")) |
|
|
|
|
|
|
|
elif (self.obj_server_driver.item(0, row).text() == "FireWire"): |
|
|
|
self.toolbox_driver_misc.setCurrentIndex(3) |
|
|
|
self.obj_driver_capture_label.setText(self.tr("Capture Ports:")) |
|
|
|
self.obj_driver_playback_label.setText(self.tr("Playback Ports:")) |
|
|
|
|
|
|
|
elif (self.obj_server_driver.item(0, row).text() == "Loopback"): |
|
|
|
self.toolbox_driver_misc.setCurrentIndex(4) |
|
|
|
|
|
|
|
else: |
|
|
|
self.toolbox_driver_misc.setCurrentIndex(0) |
|
|
|
|
|
|
|
self.slot_checkDuplexSelection(self.obj_driver_duplex.isChecked()) |
|
|
|
|
|
|
|
@pyqtSlot() |
|
|
|
def slot_saveJackSettings(self): |
|
|
|
self.saveServerSettings() |
|
|
|
self.saveDriverSettings() |
|
|
|
|
|
|
|
@pyqtSlot() |
|
|
|
def slot_resetJackSettings(self): |
|
|
|
if (self.tabWidget.currentIndex() == 0): |
|
|
|
self.loadServerSettings(True, True) |
|
|
|
elif (self.tabWidget.currentIndex() == 1): |
|
|
|
self.loadDriverSettings(True, True) |
|
|
|
|
|
|
|
@pyqtSlot() |
|
|
|
def slot_closeWithError(self): |
|
|
|
QMessageBox.critical(self, self.tr("Error"), self.tr("jackdbus is not available!\nIt's not possible to configure JACK at this point.")) |
|
|
|
self.close() |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# Allow to use this as a standalone app |
|
|
|
if __name__ == '__main__': |
|
|
|
|
|
|
|
# Additional imports |
|
|
|
import sys, icons_rc |
|
|
|
from PyQt4.QtGui import QApplication, QIcon |
|
|
|
|
|
|
|
# App initialization |
|
|
|
app = QApplication(sys.argv) |
|
|
|
|
|
|
|
# Connect to DBus |
|
|
|
if (dbus): |
|
|
|
if (initBus(dbus.SessionBus())): |
|
|
|
QMessageBox.critical(None, app.translate("JackSettingsW", "Error"), app.translate("JackSettingsW", "jackdbus is not available!\nIs not possible to configure JACK at this point.")) |
|
|
|
sys.exit(1) |
|
|
|
else: |
|
|
|
QMessageBox.critical(None, app.translate("JackSettingsW", "Error"), app.translate("JackSettingsW", "DBus is not available, cannot continue.")) |
|
|
|
sys.exit(1) |
|
|
|
|
|
|
|
# Show GUI |
|
|
|
gui = JackSettingsW(None) |
|
|
|
gui.setWindowIcon(QIcon(":/scalable/jack.svg")) |
|
|
|
gui.show() |
|
|
|
|
|
|
|
# App-Loop |
|
|
|
sys.exit(app.exec_()) |