Clarify timing controls
This commit is contained in:
@@ -12,6 +12,7 @@ from PySide6.QtWidgets import (
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QFormLayout,
|
||||
QGroupBox,
|
||||
QHeaderView,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
@@ -73,7 +74,6 @@ class ControllerWindow(QMainWindow):
|
||||
self.lastButtonPress = {}
|
||||
self.lastLockedPressedButtons = set()
|
||||
self.remapButtonsAlreadyDown = set()
|
||||
self.buttonCooldown = self.globalDebounceSeconds()
|
||||
self.remapAction = None
|
||||
self.updatingControls = False
|
||||
|
||||
@@ -124,36 +124,16 @@ class ControllerWindow(QMainWindow):
|
||||
self.buttonPressesLogged.setChecked(bool(self.config.get("button_presses_logged", True)))
|
||||
self.buttonPressesLogged.stateChanged.connect(self.buttonLoggingChanged)
|
||||
|
||||
self.globalDebounceInput = QDoubleSpinBox()
|
||||
self.globalDebounceInput.setRange(0.01, 5.00)
|
||||
self.globalDebounceInput.setSingleStep(0.05)
|
||||
self.globalDebounceInput.setDecimals(2)
|
||||
self.globalDebounceInput.setValue(self.globalDebounceSeconds())
|
||||
self.globalDebounceInput.valueChanged.connect(self.globalSettingsChanged)
|
||||
|
||||
self.globalVolumeInput = QSpinBox()
|
||||
self.globalVolumeInput.setRange(1, 100)
|
||||
self.globalVolumeInput.setValue(self.globalVolumeIncrement())
|
||||
self.globalVolumeInput.valueChanged.connect(self.globalSettingsChanged)
|
||||
|
||||
self.globalPollingInput = QSpinBox()
|
||||
self.globalPollingInput.setRange(25, 5000)
|
||||
self.globalPollingInput.setSingleStep(25)
|
||||
self.globalPollingInput.setValue(self.globalPollingIntervalMs())
|
||||
self.globalPollingInput.valueChanged.connect(self.globalSettingsChanged)
|
||||
|
||||
settingsRow = QHBoxLayout()
|
||||
settingsRow.addWidget(self.buttonPressesLogged)
|
||||
settingsRow.addStretch(1)
|
||||
settingsRow.addWidget(QLabel("Global debounce"))
|
||||
settingsRow.addWidget(self.globalDebounceInput)
|
||||
settingsRow.addWidget(QLabel("Global volume step"))
|
||||
settingsRow.addWidget(self.globalVolumeInput)
|
||||
settingsRow.addWidget(QLabel("Volume repeat ms"))
|
||||
settingsRow.addWidget(self.globalPollingInput)
|
||||
|
||||
self.bindingTable = QTableWidget(0, 5)
|
||||
self.bindingTable.setHorizontalHeaderLabels(["Button", "Spotify API Call", "Debounce", "Vol Step", "Repeat MS"])
|
||||
self.timingButton = QPushButton("Timing Settings")
|
||||
self.timingButton.clicked.connect(self.openTimingSettings)
|
||||
settingsRow.addWidget(self.timingButton)
|
||||
|
||||
self.bindingTable = QTableWidget(0, 6)
|
||||
self.bindingTable.setHorizontalHeaderLabels(["Button", "Spotify API Call", "Debounce Mode", "Debounce", "Volume Step %", "Held Repeat MS"])
|
||||
self.bindingTable.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
self.bindingTable.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.bindingTable.verticalHeader().setVisible(False)
|
||||
@@ -165,6 +145,7 @@ class ControllerWindow(QMainWindow):
|
||||
self.bindingTable.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeToContents)
|
||||
self.bindingTable.horizontalHeader().setSectionResizeMode(3, QHeaderView.ResizeToContents)
|
||||
self.bindingTable.horizontalHeader().setSectionResizeMode(4, QHeaderView.ResizeToContents)
|
||||
self.bindingTable.horizontalHeader().setSectionResizeMode(5, QHeaderView.ResizeToContents)
|
||||
|
||||
self.mapButton = QPushButton("Capture Button For Selected Action")
|
||||
self.mapButton.clicked.connect(self.startRemap)
|
||||
@@ -325,12 +306,17 @@ class ControllerWindow(QMainWindow):
|
||||
self.config["button_presses_logged"] = self.buttonPressesLogged.isChecked()
|
||||
saveConfig(self.config)
|
||||
|
||||
def globalSettingsChanged(self):
|
||||
self.config.setdefault("global_settings", {})
|
||||
self.config["global_settings"]["debounce_seconds"] = self.globalDebounceInput.value()
|
||||
self.config["global_settings"]["volume_increment"] = self.globalVolumeInput.value()
|
||||
self.config["global_settings"]["polling_interval_ms"] = self.globalPollingInput.value()
|
||||
saveConfig(self.config)
|
||||
def openTimingSettings(self):
|
||||
dialog = TimingSettingsDialog(self.config, self.currentButtonSettings, self)
|
||||
|
||||
if dialog.exec() == QDialog.Accepted:
|
||||
self.currentButtonSettings = copy.deepcopy(dialog.buttonSettings)
|
||||
|
||||
if self.selectedController() is not None and self.selectedController().get("instance_id") == self.lockedInstanceId:
|
||||
self.lockedButtonSettings = copy.deepcopy(self.currentButtonSettings)
|
||||
|
||||
self.updateBindingTable()
|
||||
self.statusLabel.setText("Timing settings updated.")
|
||||
|
||||
def lockSelectedController(self):
|
||||
controller = self.selectedController()
|
||||
@@ -394,11 +380,18 @@ class ControllerWindow(QMainWindow):
|
||||
actionBox.setCurrentIndex(actionBox.findData(self.currentBindings.get(binding, "")))
|
||||
actionBox.currentIndexChanged.connect(lambda ignored=None, row=row: self.tableRowChanged(row))
|
||||
|
||||
debounceModeBox = QComboBox()
|
||||
debounceModeBox.addItem("Global", "global")
|
||||
debounceModeBox.addItem("Off", "off")
|
||||
debounceModeBox.addItem("Custom", "custom")
|
||||
debounceModeBox.setCurrentIndex(debounceModeBox.findData(self.buttonSetting(binding, "debounce_mode", "global")))
|
||||
debounceModeBox.currentIndexChanged.connect(lambda ignored=None, row=row: self.tableRowChanged(row))
|
||||
|
||||
debounceInput = QDoubleSpinBox()
|
||||
debounceInput.setRange(0.00, 5.00)
|
||||
debounceInput.setSingleStep(0.05)
|
||||
debounceInput.setDecimals(2)
|
||||
debounceInput.setSpecialValueText("Global")
|
||||
debounceInput.setSpecialValueText("Off")
|
||||
debounceInput.setValue(self.buttonSetting(binding, "debounce_seconds", 0))
|
||||
debounceInput.valueChanged.connect(lambda ignored=None, row=row: self.tableRowChanged(row))
|
||||
|
||||
@@ -417,9 +410,10 @@ class ControllerWindow(QMainWindow):
|
||||
|
||||
self.bindingTable.setItem(row, 0, buttonItem)
|
||||
self.bindingTable.setCellWidget(row, 1, actionBox)
|
||||
self.bindingTable.setCellWidget(row, 2, debounceInput)
|
||||
self.bindingTable.setCellWidget(row, 3, volumeInput)
|
||||
self.bindingTable.setCellWidget(row, 4, pollingInput)
|
||||
self.bindingTable.setCellWidget(row, 2, debounceModeBox)
|
||||
self.bindingTable.setCellWidget(row, 3, debounceInput)
|
||||
self.bindingTable.setCellWidget(row, 4, volumeInput)
|
||||
self.bindingTable.setCellWidget(row, 5, pollingInput)
|
||||
self.bindingTable.setRowHeight(row, 34)
|
||||
|
||||
self.bindingTable.resizeColumnsToContents()
|
||||
@@ -449,9 +443,10 @@ class ControllerWindow(QMainWindow):
|
||||
|
||||
binding = buttonItem.text()
|
||||
actionBox = self.bindingTable.cellWidget(row, 1)
|
||||
debounceInput = self.bindingTable.cellWidget(row, 2)
|
||||
volumeInput = self.bindingTable.cellWidget(row, 3)
|
||||
pollingInput = self.bindingTable.cellWidget(row, 4)
|
||||
debounceModeBox = self.bindingTable.cellWidget(row, 2)
|
||||
debounceInput = self.bindingTable.cellWidget(row, 3)
|
||||
volumeInput = self.bindingTable.cellWidget(row, 4)
|
||||
pollingInput = self.bindingTable.cellWidget(row, 5)
|
||||
action = actionBox.currentData()
|
||||
|
||||
if action:
|
||||
@@ -461,7 +456,12 @@ class ControllerWindow(QMainWindow):
|
||||
|
||||
settings = {}
|
||||
|
||||
if debounceInput.value() > 0:
|
||||
debounceMode = debounceModeBox.currentData()
|
||||
|
||||
if debounceMode != "global":
|
||||
settings["debounce_mode"] = debounceMode
|
||||
|
||||
if debounceMode == "custom":
|
||||
settings["debounce_seconds"] = debounceInput.value()
|
||||
|
||||
if volumeInput.value() > 0:
|
||||
@@ -726,7 +726,7 @@ class ControllerWindow(QMainWindow):
|
||||
self.lockedButtonSettings = copy.deepcopy(self.currentButtonSettings)
|
||||
|
||||
def globalDebounceSeconds(self):
|
||||
return self.config.get("global_settings", {}).get("debounce_seconds", 0.25)
|
||||
return self.config.get("global_settings", {}).get("debounce_seconds", 0.08)
|
||||
|
||||
def globalVolumeIncrement(self):
|
||||
return self.config.get("global_settings", {}).get("volume_increment", 5)
|
||||
@@ -735,7 +735,16 @@ class ControllerWindow(QMainWindow):
|
||||
return self.config.get("global_settings", {}).get("polling_interval_ms", 120)
|
||||
|
||||
def debounceSecondsForButton(self, binding):
|
||||
return self.lockedButtonSettings.get(binding, {}).get("debounce_seconds", self.globalDebounceSeconds())
|
||||
debounceSettings = self.lockedButtonSettings.get(binding, {})
|
||||
debounceMode = debounceSettings.get("debounce_mode", "global")
|
||||
|
||||
if debounceMode == "off":
|
||||
return 0
|
||||
|
||||
if debounceMode == "custom":
|
||||
return debounceSettings.get("debounce_seconds", self.globalDebounceSeconds())
|
||||
|
||||
return self.globalDebounceSeconds()
|
||||
|
||||
def volumeIncrementForButton(self, binding):
|
||||
return self.lockedButtonSettings.get(binding, {}).get("volume_increment", self.globalVolumeIncrement())
|
||||
@@ -788,6 +797,79 @@ class SpotifySetupDialog(QDialog):
|
||||
self.accept()
|
||||
|
||||
|
||||
class TimingSettingsDialog(QDialog):
|
||||
def __init__(self, config, buttonSettings, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.config = config
|
||||
self.buttonSettings = copy.deepcopy(buttonSettings)
|
||||
|
||||
self.setWindowTitle("Timing Settings")
|
||||
|
||||
self.debounceInput = QDoubleSpinBox()
|
||||
self.debounceInput.setRange(0.01, 5.00)
|
||||
self.debounceInput.setSingleStep(0.01)
|
||||
self.debounceInput.setDecimals(2)
|
||||
self.debounceInput.setValue(self.globalDebounceSeconds())
|
||||
|
||||
self.volumeInput = QSpinBox()
|
||||
self.volumeInput.setRange(1, 100)
|
||||
self.volumeInput.setValue(self.globalVolumeIncrement())
|
||||
|
||||
self.repeatInput = QSpinBox()
|
||||
self.repeatInput.setRange(25, 5000)
|
||||
self.repeatInput.setSingleStep(25)
|
||||
self.repeatInput.setValue(self.globalPollingIntervalMs())
|
||||
|
||||
buttonGroup = QGroupBox("Button Press Timing")
|
||||
buttonLayout = QFormLayout()
|
||||
buttonLayout.addRow("Debounce", self.debounceInput)
|
||||
buttonLayout.addRow(QLabel("Used for play/pause, next, previous, mute, and other click actions. Per-button overrides can set Debounce Mode to Off for rotary encoders."))
|
||||
buttonGroup.setLayout(buttonLayout)
|
||||
|
||||
volumeGroup = QGroupBox("Spotify Volume Timing")
|
||||
volumeLayout = QFormLayout()
|
||||
volumeLayout.addRow("Spotify volume change per step (%)", self.volumeInput)
|
||||
volumeLayout.addRow("Held volume repeat speed (milliseconds)", self.repeatInput)
|
||||
volumeLayout.addRow(QLabel("Used only for Spotify volume up/down. Holding a volume button repeats at this speed."))
|
||||
volumeGroup.setLayout(volumeLayout)
|
||||
|
||||
overrideGroup = QGroupBox("Per-Button Overrides")
|
||||
overrideLayout = QVBoxLayout()
|
||||
overrideLayout.addWidget(QLabel("The mapping table can override timing for a specific button. Debounce Mode can be Global, Off, or Custom. Leave volume/repeat overrides at Global to use these defaults."))
|
||||
overrideGroup.setLayout(overrideLayout)
|
||||
|
||||
self.buttons = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Cancel)
|
||||
self.buttons.accepted.connect(self.saveAndAccept)
|
||||
self.buttons.rejected.connect(self.reject)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(buttonGroup)
|
||||
layout.addWidget(volumeGroup)
|
||||
layout.addWidget(overrideGroup)
|
||||
layout.addWidget(self.buttons)
|
||||
|
||||
self.setLayout(layout)
|
||||
self.resize(620, 300)
|
||||
|
||||
def saveAndAccept(self):
|
||||
self.config.setdefault("global_settings", {})
|
||||
self.config["global_settings"]["debounce_seconds"] = self.debounceInput.value()
|
||||
self.config["global_settings"]["volume_increment"] = self.volumeInput.value()
|
||||
self.config["global_settings"]["polling_interval_ms"] = self.repeatInput.value()
|
||||
saveConfig(self.config)
|
||||
self.accept()
|
||||
|
||||
def globalDebounceSeconds(self):
|
||||
return self.config.get("global_settings", {}).get("debounce_seconds", 0.08)
|
||||
|
||||
def globalVolumeIncrement(self):
|
||||
return self.config.get("global_settings", {}).get("volume_increment", 5)
|
||||
|
||||
def globalPollingIntervalMs(self):
|
||||
return self.config.get("global_settings", {}).get("polling_interval_ms", 120)
|
||||
|
||||
|
||||
def runGui():
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ def makeDefaultConfig():
|
||||
"default_profile_id": DEFAULT_WHEEL_PROFILE_ID,
|
||||
"button_presses_logged": True,
|
||||
"global_settings": {
|
||||
"debounce_seconds": 0.25,
|
||||
"debounce_seconds": 0.08,
|
||||
"volume_increment": 5,
|
||||
"polling_interval_ms": 120,
|
||||
},
|
||||
@@ -121,7 +121,7 @@ def normalizeConfig(config):
|
||||
config.setdefault("default_profile_id", DEFAULT_WHEEL_PROFILE_ID)
|
||||
config.setdefault("button_presses_logged", True)
|
||||
config.setdefault("global_settings", {})
|
||||
config["global_settings"].setdefault("debounce_seconds", 0.25)
|
||||
config["global_settings"].setdefault("debounce_seconds", 0.08)
|
||||
config["global_settings"].setdefault("volume_increment", 5)
|
||||
config["global_settings"].setdefault("polling_interval_ms", 120)
|
||||
config.setdefault("profiles", [])
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"default_profile_id": "friend_directinput_wheel",
|
||||
"button_presses_logged": true,
|
||||
"global_settings": {
|
||||
"debounce_seconds": 0.25,
|
||||
"debounce_seconds": 0.08,
|
||||
"volume_increment": 5,
|
||||
"polling_interval_ms": 120
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user