feat: автоподхват звука после рестарта телефона (очки играют — звук молчит)

Сценарий (железо): телефон перезапущен, очки продолжают играть — звук
не создавался (плеер живёт только по watch). Решение:
- PlaybackPosition теперь несёт itemId+audioIndex (дефолты — совместимость)
- очки: MovieController хранит itemId/audioIndex (playVideo/close), шлёт в позиции
- телефон: onPlaybackPosition → autostartAudio: если itemId есть, аудио не
  активно и не было неудачи — mirrorByItem → resolveAudioSource → play(source,
  positionMs); lastFailed защита от спама каждые 5с
- Тесты: 13 lib-core (сериализация + старый формат), 4 glasses
  (contentId/close), 70/0 phone; железо: рестарт телефона → «audio sync»
  через ~5с (diff 483), подтверждено пользователем
This commit is contained in:
Hermes Agent
2026-08-19 21:45:23 +03:00
parent 8072d0c95a
commit e29bc5032d
7 changed files with 178 additions and 14 deletions
@@ -0,0 +1,57 @@
package pw.binom.viewmate.glasses
import pw.binom.viewmate.core.protocol.PlayVideo
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue
/**
* Запоминание контента в MovieController (itemId/audioIndex) для PlaybackPosition:
* phone автоподхватывает звук, если очки играют после рестарта телефона.
* Чистые функции (как MovieControllerSeekTest) — без Android-плеера.
*/
class MovieControllerContentTest {
@Test
fun playVideoRemembersItemIdAndAudioIndex() {
val content = contentIdOnPlayVideo(
PlayVideo(
itemId = "movie-1",
title = "Акира",
videoUrl = "file:///data/viewmate/movie-1/video.mkv",
audioIndex = 2,
),
)
assertEquals("movie-1", content.itemId)
assertEquals(2, content.audioIndex)
}
@Test
fun closeClearsItemId() {
val content = contentIdOnClose()
assertNull(content.itemId)
assertEquals(0, content.audioIndex)
}
@Test
fun playbackSnapshotCarriesContentIdentity() {
val snapshot = PlaybackSnapshot(
positionMs = 65_432,
playing = true,
itemId = "movie-1",
audioIndex = 1,
)
assertEquals(65_432, snapshot.positionMs)
assertTrue(snapshot.playing)
assertEquals("movie-1", snapshot.itemId)
assertEquals(1, snapshot.audioIndex)
}
@Test
fun contentIdDefaultsToNoContent() {
val content = ContentId()
assertNull(content.itemId)
assertEquals(0, content.audioIndex)
}
}