Files
radiola-android/app/src/main/java/com/radiola/data/local/LocalStationDataSource.kt
nk 5ffaf9a924 feat(player): переключатель качества звука на экране воспроизведения
Перепроверены все 594 рабочие станции на наличие битрейт-вариантов
потока (скрипт-пробер). У 71 станции найдено по 2–4 качества
(Record-флагманы 96/64/32, zaycev 256/128/48, ВГТРК 192/128/64,
НАШЕ/Орфей/Шансон HQ и др.) — записаны в поле qualities в stations.json.
HLS (EMG) и Love (UID-привязка) корректно пропущены.

Клиент: модель StreamQuality, хранение в Room (миграция v5),
предпочтение битрейта в настройках. На экране плеера — чип текущего
качества (виден только если вариантов ≥2) и шторка «Качество звука»
со ступенями; переключение на лету без сброса now-playing, выбор
запоминается между станциями.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 12:36:47 +03:00

81 lines
3.2 KiB
Kotlin
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.

package com.radiola.data.local
import android.content.Context
import com.radiola.data.local.dto.LocalGroupDto
import com.radiola.data.local.dto.LocalStationsResponse
import com.radiola.domain.model.Station
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.serialization.json.Json
import java.io.BufferedReader
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class LocalStationDataSource @Inject constructor(
@ApplicationContext private val context: Context,
private val json: Json
) {
private var cachedResponse: LocalStationsResponse? = null
fun loadStations(): List<Station> {
android.util.Log.d("LocalStationDS", "loadStations() called")
val response = getResponse()
android.util.Log.d("LocalStationDS", "Parsed: ${response.stations.size} stations, ${response.groups.size} groups")
val groupMap = response.groups.associateBy { it.id }
return response.stations
.filter { it.enabled && !it.notWorked && it.stream != null }
.map { dto ->
val group = groupMap[dto.groupId]
val prefix = generatePrefix(dto.name)
// Определяем сеть: только станции Radio Record можно обогащать
// обложками из Record API. Остальные сети — свой источник.
val isRecord = dto.site?.contains("radiorecord", ignoreCase = true) == true
Station(
id = dto.id,
name = dto.name,
prefix = prefix,
streamUrl = dto.stream!!,
coverUrl = StationLogos.forName(dto.name) ?: StationLogos.forSite(dto.site) ?: "",
genre = group?.name ?: "",
tags = listOfNotNull(group?.name?.takeIf { it.isNotBlank() }),
sortOrder = dto.id,
source = if (isRecord) "record" else "local",
qualities = dto.qualities.orEmpty().map {
com.radiola.domain.model.StreamQuality(it.bitrate, it.url, it.type)
}
)
}
}
fun loadGroups(): List<LocalGroupDto> {
return getResponse().groups.filter { it.name.isNotBlank() }
}
fun getGroupNames(): List<String> {
return loadGroups().map { it.name }
}
private fun getResponse(): LocalStationsResponse {
android.util.Log.d("LocalStationDS", "getResponse() called")
cachedResponse?.let { return it }
val text = context.assets.open("stations.json").bufferedReader().use(BufferedReader::readText)
val parsed = json.decodeFromString(LocalStationsResponse.serializer(), text)
cachedResponse = parsed
return parsed
}
private fun generatePrefix(name: String): String {
return name.lowercase()
.replace(Regex("[^a-z0-9а-яё]+"), "_")
.trim('_')
.take(30)
}
private fun generateCoverUrl(groupName: String, stationName: String): String {
// Placeholder: return empty for now; Record API will override with real covers when available
return ""
}
}