Files
windows/PLAN.md
T
ros d5e827112a Add MusicBridge protocol documentation and implement system volume control
- Created PROTOCOL.md to outline the MusicBridge protocol v1, detailing setup, TLS, pairing, state management, and command structure.
- Implemented SystemVolume class for managing system audio levels, including methods for setting, reading, changing, and muting volume.
- Added unit tests for the MusicBridge agent, covering pairing, identity storage, command validation, and media state management.
- Included tests for real-time media reading from Windows and ensured proper handling of artwork caching and retrieval.
2026-09-09 01:05:52 +03:00

182 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MusicBridge — план проекта
Обновлено: 2026-09-09. Репозиторий находится в `MusicBridge.Agent/`.
## Цель
Личный пульт на **нативном iPhone-приложении** для музыки на Windows в одной
Wi-Fi сети. Звук играет на ПК. Телефон показывает трек, исполнителя, обложку,
позицию и позволяет управлять воспроизведением и системной громкостью ПК.
## Решения пользователя — не менять без его указания
- Windows + iPhone; своего Mac сейчас нет.
- **Не делать Safari, PWA, веб-страницы или веб-приложение.** Клиент — Swift/SwiftUI.
- iPhone-часть пока не начинать. Сначала довести Windows-агент и протокол.
- Работать по этапам, самостоятельно редактировать файлы и проверять сборку.
- Основные источники: Яндекс Музыка и SoundCloud в браузере, через текущую
системную медиасессию Windows.
- Нужны безопасное сопряжение, автоматическое переподключение, затем поиск ПК.
- В будущем желательны Lock Screen, Dynamic Island и системные команды iOS.
## Границы возможностей
- «Любой звук» относится к системной громкости. Метаданные и команды зависят от
того, что конкретный плеер передаёт в Windows Media Session.
- Позиция вычисляется из Position + времени после LastUpdatedTime с учётом
PlaybackRate. Нельзя считать Position постоянно обновляемым значением.
- Не обещать работу перемотки или переключений без проверки возможностей плеера.
- Для сборки/подписи нативного iOS-приложения потребуется доступ к macOS/Xcode;
способ установки на личный iPhone нужно выбрать перед началом iOS-этапа.
- Возможности iOS в фоне, Lock Screen и Dynamic Island исследовать отдельно.
Не имитировать воспроизведение беззвучным аудио ради фоновой работы.
- HTTPS/WebSocket внутри агента — транспорт для нативного клиента, не веб-интерфейс.
## Архитектура
Windows Media Session → общий MediaService → HTTPS/WSS → будущий SwiftUI-клиент.
Windows Core Audio → системная громкость устройства вывода по умолчанию.
Консоль и сеть используют одни команды и одни правила расчёта позиции.
## Этапы и TODO
### 1. Windows: чтение и локальное управление
- [x] Название, исполнитель, источник, состояние и длительность.
- [x] Вычисление текущей позиции с учётом времени и скорости.
- [x] Play/pause, следующий/предыдущий трек, перемотка ±10 секунд.
- [x] Системная громкость ±5%, mute.
- [x] Проверки поддержки команд и обработка отказов.
- [x] Сборка исходной консольной версии: 0 ошибок, 0 предупреждений.
- [x] Проверен запуск с реальным плеером и чтение громкости.
- [ ] Полная ручная проверка кнопок в Яндекс Музыке и SoundCloud.
### 2. Windows: общий сервис и сетевой протокол
- [x] Вынести чтение/команды из Program.cs в общий сервис.
- [x] Добавить абсолютную перемотку и установку громкости для ползунков iPhone.
- [x] Версионированное JSON-состояние, возможности плеера, результаты команд.
- [x] HTTPS для команд, WSS для обновлений состояния; без веб-интерфейса.
- [x] Ограниченное по времени сопряжение по коду, аутентификация команд.
- [x] Сертификат агента и отпечаток для будущего закрепления сертификата на iPhone.
- [x] Проверки протокола, ошибочного ввода и доступа без авторизации.
- [x] Обновить этот файл и документацию по фактическим результатам.
### 3. Довести агент перед iPhone
- [x] Обложка из медиасессии; ограничение размера, кеш и смена трека.
- [x] Системные события Windows для быстрых обновлений; таймер для прогресса.
- [x] Постоянные доверенные устройства, безопасное хранение хешей токенов, отзыв доступа.
- [x] Постоянный сертификат, защищённое хранилище Windows DPAPI, блокировка второго агента.
- [ ] Обновление истекающего сертификата с явным повторным сопряжением.
- [ ] QR-сопряжение с адресом и отпечатком сертификата.
- [x] Заготовки: payload для QR, проверка адреса/срока, клавиша I.
- [x] Заготовки: DNS-SD descriptor и авторизованный /v1/info; без multicast.
- [ ] Bonjour/mDNS для поиска из нативного приложения.
- [ ] Проверить подключение со второго устройства в домашней сети.
- [ ] Проверить смену плеера/аудиоустройства, отсутствие плеера, сон/пробуждение,
отключение Wi-Fi и несколько клиентов.
- [ ] Tray-интерфейс, автозапуск, удобная установка; правила брандмауэра только
для нужной локальной сети, без открытия доступа в интернет.
### 4. Нативное приложение iPhone — отложено пользователем
- [ ] Согласовать macOS/Xcode, подпись и установку на личный iPhone.
- [ ] SwiftUI: подключение, список компьютеров, сопряжение и сохранение в Keychain.
- [ ] Обложка, трек, исполнитель, плавный прогресс, кнопки и ползунки.
- [ ] Проверка сертификата ПК, переподключение и восстановление состояния.
- [ ] Отключать недоступные команды, отображать ошибки и потерю связи.
- [ ] Проверка на физическом iPhone.
### 5. Дополнительные возможности iOS
- [ ] Исследовать и проверить Live Activities / Dynamic Island / App Intents.
- [ ] Зафиксировать реальные ограничения системного управления и фона.
## Как продолжать работу
1. Прочитать этот файл, затем текущие исходники и `git status`.
2. Не переписывать уже работающие функции без необходимости.
3. Выполнить конкретный этап, проверить сборку и соответствующие проверки.
4. Отдельно указать: что проверено автоматически, что на реальной Windows,
а что ещё требует телефона/ручной проверки.
5. Обновить чекбоксы, результаты и следующий шаг здесь до завершения работы.
## Проверки и следующий шаг
2026-09-09:
- Последний этап — заготовки подключения: Release-сборка без ошибок/предупреждений,
**82 автоматические проверки прошли** (`dotnet run --project tests/MusicBridge.Agent.Tests.csproj -c Release --no-build`).
Проверены payload, адреса, истёкший код, descriptor и авторизация /v1/info.
Debug-сборку удерживал запущенный агент; его не останавливали. Новая сборка в Release.
Реальная медиасессия в этом прогоне не проверялась; проверки ниже — с прошлого этапа.
- Сборка агента и тестового проекта: **0 ошибок, 0 предупреждений**.
- `dotnet run --project tests/MusicBridge.Agent.Tests.csproj -- --live-read`:
**74 проверки прошло** (71 общая + 3 с реальной медиасессией/обложкой).
Проверены расчёт позиции, валидация, срок/одноразовость кода, блокировка после
10 попыток, авторизация HTTPS/WSS, ошибки JSON и размер запроса, доставка
абсолютной перемотки тестовому сервису, поток состояния и закрытие WebSocket.
Добавлены проверки размера/формата обложки, отмены чтения, очистки старого кеша,
авторизации скачивания и 404, доставки событий без ожидания таймера,
объединения 1000 уведомлений и снятия подписки сервером при остановке.
Проверены сохранение/повторное открытие сертификата и устройств, реальный HTTPS
со восстановленным сертификатом/токеном, DPAPI, блокировка второго экземпляра,
ошибки записи, отказ от подмены повреждённого хранилища, постоянный отзыв доступа,
отключение открытого WSS и запрет HTTP-команд отозванным токеном.
- В тестах добавлена обработка исключений верхнего уровня. Проверен
`--test-failure`: текст `TEST FAILED` и выход 1 вместо необработанного исключения,
вызвавшего ранее окно ошибки Windows. Тестовые файлы создаются отдельно от
рабочего хранилища и удаляются после проверки.
- Эти проверки не меняют реальную музыку/громкость. Ручная проверка команд
конкретных плееров и физического iPhone всё ещё не выполнена.
- Обновлённый агент запущен в обычном сеансе Windows на loopback-порту 18765:
HTTPS-сервер стартовал, реальная медиасессия, состояние Paused, длительность
и системная громкость прочитаны. После проверки тестовый запуск остановлен.
- После добавления обложки в режиме `--live-read` прочитан реальный PNG размером
438760 байт. Повторное чтение состояния сохранило тот же ID кешированной обложки.
Подписки WinRT создаются успешно. Доставка событий проверена тестовым сервисом;
ручная смена треков/плееров во время работы агента ещё требует проверки.
- В песочнице Windows Media Session может быть недоступна. Не выдавать такую
ошибку за отсутствие Windows API на машине пользователя.
Текущие ограничения сетевого этапа:
- Состояние обновляется по событиям Windows и резервному таймеру ~500 мс.
Метаданные/обложка перечитываются по событию либо через 10 секунд.
- В кеше только текущая обложка, максимум 2 МиБ; PNG/JPEG/GIF/WebP по сигнатуре,
без декодирования на сервере. Скачивание требует авторизации.
- Сертификат и хеши токенов сохраняются в `%LOCALAPPDATA%\MusicBridge\identity.dat`
под Windows DPAPI текущего пользователя. При обычном перезапуске доверие сохраняется.
В консоли `1`…`8` отзывают доступ устройства по номеру; `B` открывает сопряжение.
- Сертификат действует 5 лет; автоматическое обновление ещё не реализовано.
При повреждении/недоступности хранилища или истечении сертификата агент завершается
с ошибкой и не создаёт молча новую идентичность. Восстановление описано в PROTOCOL.md.
- По умолчанию только loopback. `--lan` включает IPv4-сеть; брандмауэр не меняется.
- QR, mDNS, iPhone UI и интеграции iOS ещё не реализованы.
Следующий шаг: этап 3 — QR-сопряжение (адрес, код, закрепляемый отпечаток),
затем Bonjour/mDNS и проверка с другого устройства. iPhone-клиент пока не начинать.
Заготовки готовы; точные границы и следующие шаги — в `CONNECTION-ROADMAP.md`.
Начать разработку iOS только после новой команды пользователя.
## Карта файлов
- `Program.cs`: запуск, аргументы, консольные клавиши и отображение состояния.
- `Media/MediaService.cs`: чтение Windows Media Session и выполнение всех команд.
- `Media/TimelineMath.cs`: вычисление позиции и границ перемотки.
- `Media/Contracts.cs`: состояние, возможности, команды и их валидация.
- `Media/ArtworkCache.cs`: ограниченное чтение обложки, определение типа и кеш по хешу.
- `SystemVolume.cs`: Windows Core Audio, громкость устройства вывода по умолчанию.
- `Network/RemoteServer.cs`: HTTPS API и обложки, WSS, события/таймер и лимиты.
- `Network/PairingService.cs`: код сопряжения, доверенные устройства, проверка/отзыв токенов.
- `Network/IdentityStore.cs`: постоянный сертификат и устройства, атомарная запись и блокировка.
- `Network/UserProtection.cs`: Windows DPAPI текущего пользователя.
- `Network/AgentCertificate.cs`: создание сертификата TLS для первого запуска.
- `PROTOCOL.md`: команды запуска и точный контракт будущего iPhone-клиента.
- `CONNECTION-ROADMAP.md`: заготовки QR/DNS-SD и шаги будущего подключения.
- `Network/ConnectionInvitation.cs`: данные для QR, без генерации картинки.
- `Network/DiscoveryDescriptor.cs`: описание DNS-SD, без сетевой рассылки.
- `tests/`: исполняемые проверки без дополнительных тестовых NuGet-пакетов.