diff --git a/menus.py b/menus.py index c1f39b5..5a4e9bc 100644 --- a/menus.py +++ b/menus.py @@ -1,12 +1,13 @@ import re +import logging from os import remove try: - from PyQt6 import QtCore, QtGui, QtWidgets + from PyQt6 import QtCore, QtGui, QtWidgets, QtMultimedia from PyQt6.QtGui import QAction except ImportError: print("PyQt5 fallback (menus.py)") - from PyQt5 import QtCore, QtGui, QtWidgets + from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia from PyQt5.QtWidgets import QAction import ostools @@ -20,6 +21,8 @@ from parsetools import lexMessage QString = str _datadir = ostools.getDataDir() +# Logger +PchumLog = logging.getLogger("pchumLogger") class PesterQuirkItem(QtWidgets.QTreeWidgetItem): @@ -1559,6 +1562,21 @@ class PesterOptions(QtWidgets.QDialog): # Sound widget = QtWidgets.QWidget() + # Choose audio device + audioDeviceLabel = QtWidgets.QLabel("Audio output device:") + self.audioDeviceBox = QtWidgets.QComboBox(self) + current_audio_device = self.config.audioDevice() + active_index = None + try: + for i, output in enumerate(QtMultimedia.QMediaDevices.audioOutputs()): + self.audioDeviceBox.addItem(f"{output.description()}", output.id()) + if output.id() == current_audio_device: + active_index = i + if active_index is not None: + self.audioDeviceBox.setCurrentIndex(active_index) + except AttributeError: + PchumLog.warning("Can't get audio devices, not using PyQt6 QtMultimedia?") + layout_sound = QtWidgets.QVBoxLayout(widget) layout_sound.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) layout_sound.addWidget(self.soundcheck) @@ -1574,6 +1592,10 @@ class PesterOptions(QtWidgets.QDialog): layout_indent.setContentsMargins(22, 0, 0, 0) layout_sound.addLayout(layout_indent) layout_sound.addSpacing(15) + layout_audioDevice = QtWidgets.QHBoxLayout() + layout_audioDevice.addWidget(audioDeviceLabel) + layout_audioDevice.addWidget(self.audioDeviceBox) + layout_sound.addLayout(layout_audioDevice) mvol = QtWidgets.QLabel("Master Volume:", self) # If we can't set the volume, grey this out as well # ~mvol.setEnabled(parent.canSetVolume()) diff --git a/pesterchum.py b/pesterchum.py index 9582db7..c0a8c53 100755 --- a/pesterchum.py +++ b/pesterchum.py @@ -2451,6 +2451,10 @@ class PesterWindow(MovingWindow): self.honksound, ] + audio_device = self.config.audioDevice() + if audio_device: + self.setAudioDevice(audio_device) + def setVolume(self, vol_percent): vol = vol_percent / 100.0 for sound in self.sounds: @@ -2466,6 +2470,18 @@ class PesterWindow(MovingWindow): except Exception as err: PchumLog.warning("Couldn't set volume: %s", err) + def setAudioDevice(self, device_id: bytes): + """Sets the audio device for all sound effects, only works with QtMultimedia. + + Device_id is an unique identifier for the audio device in bytes.""" + if "QtMultimedia" not in globals(): + PchumLog.warning("Not using QtMultimedia, can't set audio device.") + return + for output in QtMultimedia.QMediaDevices.audioOutputs(): + if device_id == output.id(): + for sound in self.sounds: + sound.setAudioDevice(output) + def canSetVolume(self): """Returns the state of volume setting capabilities.""" # If the volume can be changed by Pesterchum. @@ -3314,6 +3330,12 @@ class PesterWindow(MovingWindow): if volumesetting != curvolume: self.config.set("volume", volumesetting) self.setVolume(volumesetting) + # Audio device + audio_device_id = self.optionmenu.audioDeviceBox.currentData() + # ID is a QByteArray, but we can't store that, so it needs to be decoded first. + if audio_device_id: + self.config.set("audioDevice", str(audio_device_id, "utf-8")) + self.setAudioDevice(audio_device_id) # timestamps timestampsetting = self.optionmenu.timestampcheck.isChecked() self.config.set("showTimeStamps", timestampsetting) diff --git a/user_profile.py b/user_profile.py index 047db54..d6b4db6 100644 --- a/user_profile.py +++ b/user_profile.py @@ -524,6 +524,15 @@ with a backup from: %s" def volume(self): return self.config.get("volume", 100) + def audioDevice(self): + """Return audio device ID. + + Can't store a QByteArray, so decode/encoding is required.""" + device = self.config.get("audioDevice", None) + if device: + device = device.encode(encoding="utf-8") + return device + def trayMessage(self): return self.config.get("traymsg", True)