From 53cd1601dce2de84a67990f6f0d69357f0d2dbfd Mon Sep 17 00:00:00 2001 From: nk Date: Thu, 4 Jun 2026 19:03:44 +0300 Subject: [PATCH] =?UTF-8?q?fix(recordings):=20=D0=BD=D0=B5=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D1=81=D0=B0=D1=82=D1=8C=20=D0=BF=D0=BB=D0=B5=D0=B5?= =?UTF-8?q?=D1=80=D1=83=20=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D0=B8;=20=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=8C=D1=88=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=BA=D0=B0=20=D0=BE=D0=B1=D0=BB=D0=BE=D0=B6=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug1: плеер записи (singleton ExoPlayer) не глушился при закрытии шторки и уходе с экрана → аудио-сирота без управления, запуск радио конфликтовал. Теперь воспроизведение записи останавливается на onDismiss и onDispose экрана записей, а старт радио глушит плеер записи (взаимоисключение). Bug2: обложка/трек на открытом плеере обновлялись с задержкой при записи. Эмиссия спектра ограничена ~45/с (было ~86/с) — меньше перегруз перерисовки; поллинг now-playing в захвате маркеров ускорен 15с→8с (точнее тайм-коды). Co-Authored-By: Claude Opus 4.8 --- .../data/repository/RecordingRepositoryImpl.kt | 2 +- .../main/java/com/radiola/service/AudioSpectrum.kt | 9 ++++++++- .../java/com/radiola/ui/player/PlayerViewModel.kt | 6 +++++- .../com/radiola/ui/recordings/RecordingsScreen.kt | 13 ++++++++++--- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/radiola/data/repository/RecordingRepositoryImpl.kt b/app/src/main/java/com/radiola/data/repository/RecordingRepositoryImpl.kt index aaf7e50..d6a3814 100644 --- a/app/src/main/java/com/radiola/data/repository/RecordingRepositoryImpl.kt +++ b/app/src/main/java/com/radiola/data/repository/RecordingRepositoryImpl.kt @@ -97,7 +97,7 @@ class RecordingRepositoryImpl @Inject constructor( launch { while (isActive) { try { nowPlayingRepository.refreshNowPlaying() } catch (_: Exception) {} - delay(15_000) + delay(8_000) // чаще — точнее тайм-коды треков в записи } } nowPlayingRepository.getNowPlaying(station.id) diff --git a/app/src/main/java/com/radiola/service/AudioSpectrum.kt b/app/src/main/java/com/radiola/service/AudioSpectrum.kt index 411df49..a20d072 100644 --- a/app/src/main/java/com/radiola/service/AudioSpectrum.kt +++ b/app/src/main/java/com/radiola/service/AudioSpectrum.kt @@ -86,6 +86,7 @@ class AudioSpectrumAnalyzer( private var channelCount = 2 private var pcm16 = true private var sampleRate = 44100 + private var lastEmit = 0L // Автогейн: бегущий пик амплитуды — чтобы столбики всегда использовали всю // высоту независимо от громкости трека. private var agcPeak = 1e-4f @@ -159,6 +160,12 @@ class AudioSpectrumAnalyzer( smoothed[band] = if (v > prev) v else prev * 0.55f + v * 0.45f out[band] = smoothed[band] } - _spectrum.value = out + // Считаем сглаживание каждый хоп (плавность), но эмитим в UI ~45/с, чтобы + // не перегружать перерисовку плеера. + val now = System.nanoTime() + if (now - lastEmit >= 22_000_000L) { + lastEmit = now + _spectrum.value = out + } } } diff --git a/app/src/main/java/com/radiola/ui/player/PlayerViewModel.kt b/app/src/main/java/com/radiola/ui/player/PlayerViewModel.kt index f68c18d..584f890 100644 --- a/app/src/main/java/com/radiola/ui/player/PlayerViewModel.kt +++ b/app/src/main/java/com/radiola/ui/player/PlayerViewModel.kt @@ -37,7 +37,8 @@ class PlayerViewModel @Inject constructor( private val settingsRepository: SettingsRepository, private val recordingRepository: RecordingRepository, private val pushHistoryUseCase: PushHistoryUseCase, - private val loveStreamResolver: com.radiola.data.remote.LoveStreamResolver + private val loveStreamResolver: com.radiola.data.remote.LoveStreamResolver, + private val recordingPlaybackController: com.radiola.service.RecordingPlaybackController ) : ViewModel() { val isPlaying: StateFlow = playerController.isPlaying @@ -98,6 +99,9 @@ class PlayerViewModel @Inject constructor( } fun play(station: Station, playlist: List? = null) { + // Глушим плеер записи, если он играл — иначе два ExoPlayer'а конфликтуют + // (радио не стартует, запись зависает без управления). + recordingPlaybackController.stop() _currentStation.value = station _currentTrack.value = null _playlist.value = playlist ?: _stations.value diff --git a/app/src/main/java/com/radiola/ui/recordings/RecordingsScreen.kt b/app/src/main/java/com/radiola/ui/recordings/RecordingsScreen.kt index a06f908..be8cf6c 100644 --- a/app/src/main/java/com/radiola/ui/recordings/RecordingsScreen.kt +++ b/app/src/main/java/com/radiola/ui/recordings/RecordingsScreen.kt @@ -48,6 +48,13 @@ fun RecordingsScreen( val isRecording by viewModel.isRecording.collectAsState() val colors = RadiolaTheme.colors var playing by remember { mutableStateOf(null) } + // Плеер записи — singleton-контроллер; держим его VM здесь, чтобы корректно + // ОСТАНОВИТЬ воспроизведение при закрытии шторки и уходе с экрана (иначе + // аудио продолжает играть без UI и конфликтует с радио). + val recPlayerVm: RecordingPlayerViewModel = hiltViewModel() + DisposableEffect(Unit) { + onDispose { recPlayerVm.close() } + } Column( modifier = Modifier @@ -133,14 +140,14 @@ fun RecordingsScreen( // налезает на системную навигацию. playing?.let { rec -> ModalBottomSheet( - onDismissRequest = { playing = null }, + onDismissRequest = { recPlayerVm.close(); playing = null }, sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), containerColor = colors.bgBase ) { RecordingPlayerSheet( recording = rec, - onDismiss = { playing = null }, - viewModel = hiltViewModel() + onDismiss = { recPlayerVm.close(); playing = null }, + viewModel = recPlayerVm ) } }