diff --git a/app_new.py b/app_new.py index 7f6d3b5..e1fc87d 100644 --- a/app_new.py +++ b/app_new.py @@ -1,10 +1,26 @@ import sys + +from PySide6.QtCore import QSettings from PySide6.QtWidgets import QApplication + +import build_info +from audio.system_volume import set_volume from ui.main_window_new import MainWindowNew def run_app_new(): app = QApplication(sys.argv) + _apply_startup_volume() window = MainWindowNew(app) window.show() sys.exit(app.exec()) + + +def _apply_startup_volume(): + settings = QSettings("car_ui", "ui") + raw = settings.value("sound/base_volume", build_info.DEFAULT_SOUND_VOLUME) + try: + value = int(raw) + except (TypeError, ValueError): + value = build_info.DEFAULT_SOUND_VOLUME + set_volume(value) diff --git a/audio/__init__.py b/audio/__init__.py new file mode 100644 index 0000000..a179b16 --- /dev/null +++ b/audio/__init__.py @@ -0,0 +1 @@ +"""Audio helpers.""" diff --git a/audio/system_volume.py b/audio/system_volume.py new file mode 100644 index 0000000..9acbe4a --- /dev/null +++ b/audio/system_volume.py @@ -0,0 +1,24 @@ +import shutil +import subprocess + + +def set_volume(value: int): + value = max(0, min(100, value)) + if shutil.which("wpctl"): + _run_cmd(["wpctl", "set-volume", "@DEFAULT_AUDIO_SINK@", f"{value}%"]) + return + if shutil.which("amixer"): + _run_cmd(["amixer", "sset", "PCM", f"{value}%"]) + + +def _run_cmd(args: list[str]): + try: + subprocess.run( + args, + capture_output=True, + text=True, + timeout=1, + check=False, + ) + except (OSError, subprocess.SubprocessError): + pass diff --git a/build_info.py b/build_info.py index 761fedd..7705b90 100644 --- a/build_info.py +++ b/build_info.py @@ -9,6 +9,7 @@ VERSION = "0.1.0-dev" BUILD_DATE = "dev" GIT_HASH = "dev" DEVICE_MODEL = "Raspberry Pi" +DEFAULT_SOUND_VOLUME = 100 def get_device_model() -> str: diff --git a/screens/setting/sound_screen.py b/screens/setting/sound_screen.py index f8fb7f3..d5d9e13 100644 --- a/screens/setting/sound_screen.py +++ b/screens/setting/sound_screen.py @@ -1,4 +1,4 @@ -from PySide6.QtCore import Qt, QSettings +from PySide6.QtCore import Qt, QSettings, QTimer from PySide6.QtGui import QFont from PySide6.QtWidgets import ( QWidget, @@ -11,6 +11,8 @@ from PySide6.QtWidgets import ( QScrollArea, QScroller, ) +from audio.system_volume import set_volume +import build_info class SoundScreen(QWidget): @@ -18,6 +20,10 @@ class SoundScreen(QWidget): super().__init__() self._on_eq = on_eq self._settings = QSettings("car_ui", "ui") + self._pending_volume: int | None = None + self._volume_apply_timer = QTimer(self) + self._volume_apply_timer.setSingleShot(True) + self._volume_apply_timer.timeout.connect(self._flush_volume) root = QVBoxLayout(self) root.setContentsMargins(0, 0, 0, 0) @@ -57,9 +63,21 @@ class SoundScreen(QWidget): def _read_bool(self, key: str, default: bool) -> bool: return _read_bool_setting(self._settings, key, default) + def _queue_volume_apply(self, value: int): + self._pending_volume = value + self._volume_apply_timer.start(120) + + def _flush_volume(self): + if self._pending_volume is None: + return + self._set_system_volume(self._pending_volume) + + def _set_system_volume(self, value: int): + set_volume(value) + def _build_volume_card(self) -> QWidget: card, body = _card("Громкость") - default_value = 60 + default_value = build_info.DEFAULT_SOUND_VOLUME value = self._read_int("sound/base_volume", default_value) row, slider, value_label = _slider_row( "Базовая громкость", @@ -71,6 +89,7 @@ class SoundScreen(QWidget): slider.valueChanged.connect( lambda v: self._settings.setValue("sound/base_volume", v) ) + slider.valueChanged.connect(self._queue_volume_apply) body.addWidget(row) return card