Compare commits

...

3 Commits

Author SHA1 Message Date
3f4c49ccf2 add priority mac 2026-04-01 04:05:22 +03:00
126e27e29f add priority mac 2026-04-01 04:00:52 +03:00
9ae9e7873a add bl music_mac 2026-04-01 03:54:26 +03:00
3 changed files with 62 additions and 9 deletions

2
app.py
View File

@ -34,6 +34,8 @@ def _apply_startup_sound_defaults():
settings.setValue("sound/premute_volume", premute_volume)
if not settings.contains("sound/ducking_volume"):
settings.setValue("sound/ducking_volume", ducking_volume)
if not settings.contains("bluetooth/music_mac"):
settings.setValue("bluetooth/music_mac", "")
applied_volume = settings.value("sound/base_volume", base_volume)
try:

View File

@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any
from PySide6.QtCore import QObject, Signal
from PySide6.QtCore import QObject, Signal, QSettings
@dataclass
@ -71,9 +71,21 @@ class MediaSourceController(ABC):
class BluetoothController(MediaSourceController):
"""Контроллер для Bluetooth аудио."""
def __init__(self, bt_service: Any):
self._bt_service = bt_service
self._music_mac: str | None = None
def set_music_mac(self, mac: str | None) -> None:
"""Установить приоритетный MAC для музыки."""
self._music_mac = mac
# Синхронизируем с сервисом
if self._bt_service:
self._bt_service.set_music_mac(mac)
def get_music_mac(self) -> str | None:
"""Получить приоритетный MAC для музыки."""
return self._music_mac
@property
def name(self) -> str:
@ -184,15 +196,21 @@ class MediaController(QObject):
def __init__(self, bt_service: Any = None, parent: QObject = None):
super().__init__(parent)
self._bt_service = bt_service
self._settings = QSettings("car_ui", "ui")
self._controllers: dict[str, MediaSourceController] = {}
self._current_mode: str = "bluetooth"
# Регистрируем контроллеры
self._register_controllers()
def _register_controllers(self) -> None:
"""Зарегистрировать все доступные контроллеры."""
self._controllers["bluetooth"] = BluetoothController(self._bt_service)
bt_controller = BluetoothController(self._bt_service)
# Читаем приоритетный MAC из настроек
music_mac = self._settings.value("bluetooth/music_mac", "")
if music_mac:
bt_controller.set_music_mac(music_mac)
self._controllers["bluetooth"] = bt_controller
self._controllers["carplay"] = CarPlayController()
# В будущем можно добавить:
# self._controllers["aux"] = AuxController()
@ -203,8 +221,15 @@ class MediaController(QObject):
# Если переключаемся с Bluetooth на CarPlay - ставим паузу
if self._current_mode == "bluetooth" and mode == "carplay":
self._controllers["bluetooth"].pause()
elif self._current_mode == "carplay" and mode == "bluetooth":
self._controllers["bluetooth"].play()
# Если переключаемся на Bluetooth - подключаем приоритетное устройство
elif mode == "bluetooth":
bt_controller = self._controllers["bluetooth"]
music_mac = bt_controller.get_music_mac()
if music_mac:
# Пытаемся подключить приоритетное устройство
bt_controller.connect_device(music_mac)
self._current_mode = mode
# Сигнал о смене режима для обновления UI
self.metadata_changed.emit(self.get_metadata())

View File

@ -47,6 +47,7 @@ class BluetoothService(QObject):
super().__init__(parent)
self._log_path = Path("~/.cache/car_ui/bluetooth.log").expanduser()
self._last_error = ""
self._settings = QSettings("car_ui", "ui")
# === Public API ===
@ -95,32 +96,57 @@ class BluetoothService(QObject):
return info.get("Connected", "no") == "yes"
def connect_device(self, mac: str) -> bool:
"""Подключиться к устройству."""
"""Подключиться к устройству.
При успешном подключении обновляет bluetooth/music_mac.
"""
self._last_error = ""
self._run_cmd(["bluetoothctl", "trust", mac])
result = self._run_cmd(["bluetoothctl", "connect", mac])
success = not self._last_error
if success:
# Обновляем приоритетный MAC
self._settings.setValue("bluetooth/music_mac", mac)
self.connected_changed.emit(mac, success)
return success
def disconnect_device(self, mac: str) -> bool:
"""Отключить устройство."""
"""Отключить устройство.
Если это устройство было в bluetooth/music_mac, обнуляем настройку.
"""
self._last_error = ""
result = self._run_cmd(["bluetoothctl", "disconnect", mac])
success = not self._last_error
# Если отключаем приоритетное устройство, обнуляем настройку
if success and self._settings.value("bluetooth/music_mac") == mac:
self._settings.setValue("bluetooth/music_mac", "")
self.connected_changed.emit(mac, False)
return success
def remove_device(self, mac: str) -> bool:
"""Удалить устройство из списка сопряженных."""
"""Удалить устройство из списка сопряженных.
Если это устройство было в bluetooth/music_mac, обнуляем настройку.
"""
self._last_error = ""
# Сначала отключаем, если подключено
if self.is_connected(mac):
self._run_cmd(["bluetoothctl", "disconnect", mac])
result = self._run_cmd(["bluetoothctl", "remove", mac])
success = not self._last_error
# Если удаляем приоритетное устройство, обнуляем настройку
if success and self._settings.value("bluetooth/music_mac") == mac:
self._settings.setValue("bluetooth/music_mac", "")
return success
def set_music_mac(self, mac: str | None) -> None:
"""Установить приоритетный MAC для музыки."""
if mac:
self._settings.setValue("bluetooth/music_mac", mac)
else:
self._settings.setValue("bluetooth/music_mac", "")
def make_discoverable(self, timeout_sec: int = 10) -> bool:
"""Сделать устройство видимым для сопряжения.