Make format automatically update when stats for nerds are displayed
This commit is contained in:
parent
43fda751b6
commit
192263d95b
4 changed files with 46 additions and 56 deletions
|
@ -284,7 +284,7 @@ interface Database {
|
||||||
fun artistSongs(artistId: String): Flow<List<DetailedSong>>
|
fun artistSongs(artistId: String): Flow<List<DetailedSong>>
|
||||||
|
|
||||||
@Query("SELECT * FROM Format WHERE songId = :songId")
|
@Query("SELECT * FROM Format WHERE songId = :songId")
|
||||||
fun format(songId: String): Flow<Format>
|
fun format(songId: String): Flow<Format?>
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Song JOIN Format ON id = songId WHERE contentLength IS NOT NULL AND totalPlayTimeMs > 0 ORDER BY Song.ROWID DESC")
|
@Query("SELECT * FROM Song JOIN Format ON id = songId WHERE contentLength IS NOT NULL AND totalPlayTimeMs > 0 ORDER BY Song.ROWID DESC")
|
||||||
|
|
|
@ -666,9 +666,7 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
|
||||||
}
|
}
|
||||||
|
|
||||||
when (val status = body.playabilityStatus?.status) {
|
when (val status = body.playabilityStatus?.status) {
|
||||||
"OK" -> body.streamingData?.adaptiveFormats?.findLast { format ->
|
"OK" -> body.streamingData?.highestQualityFormat?.let { format ->
|
||||||
format.itag == 251 || format.itag == 140
|
|
||||||
}?.let { format ->
|
|
||||||
val mediaItem = runBlocking(Dispatchers.Main) {
|
val mediaItem = runBlocking(Dispatchers.Main) {
|
||||||
player.findNextMediaItemById(videoId)
|
player.findNextMediaItemById(videoId)
|
||||||
}
|
}
|
||||||
|
@ -694,8 +692,7 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
|
||||||
itag = format.itag,
|
itag = format.itag,
|
||||||
mimeType = format.mimeType,
|
mimeType = format.mimeType,
|
||||||
bitrate = format.bitrate,
|
bitrate = format.bitrate,
|
||||||
loudnessDb = body.playerConfig?.audioConfig?.loudnessDb?.toFloat()
|
loudnessDb = body.playerConfig?.audioConfig?.normalizedLoudnessDb,
|
||||||
?.plus(7),
|
|
||||||
contentLength = format.contentLength,
|
contentLength = format.contentLength,
|
||||||
lastModified = format.lastModified
|
lastModified = format.lastModified
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,6 @@ import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
@ -16,7 +15,7 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.text.BasicText
|
import androidx.compose.foundation.text.BasicText
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
@ -35,7 +34,6 @@ import it.vfsfitvnm.innertube.requests.player
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.Database
|
||||||
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
||||||
import it.vfsfitvnm.vimusic.models.Format
|
import it.vfsfitvnm.vimusic.models.Format
|
||||||
import it.vfsfitvnm.vimusic.query
|
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
|
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.onOverlay
|
import it.vfsfitvnm.vimusic.ui.styling.onOverlay
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.overlay
|
import it.vfsfitvnm.vimusic.ui.styling.overlay
|
||||||
|
@ -44,8 +42,10 @@ import it.vfsfitvnm.vimusic.utils.color
|
||||||
import it.vfsfitvnm.vimusic.utils.medium
|
import it.vfsfitvnm.vimusic.utils.medium
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun StatsForNerds(
|
fun StatsForNerds(
|
||||||
|
@ -67,9 +67,36 @@ fun StatsForNerds(
|
||||||
mutableStateOf(binder.cache.getCachedBytes(mediaId, 0, -1))
|
mutableStateOf(binder.cache.getCachedBytes(mediaId, 0, -1))
|
||||||
}
|
}
|
||||||
|
|
||||||
val format by remember(mediaId) {
|
var format by remember {
|
||||||
Database.format(mediaId).distinctUntilChanged()
|
mutableStateOf<Format?>(null)
|
||||||
}.collectAsState(initial = null, context = Dispatchers.IO)
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(mediaId) {
|
||||||
|
Database.format(mediaId).distinctUntilChanged().collectLatest {
|
||||||
|
if (it?.itag == null) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
delay(3000)
|
||||||
|
Innertube.player(PlayerBody(videoId = mediaId))?.onSuccess { response ->
|
||||||
|
response.streamingData?.highestQualityFormat?.let { format ->
|
||||||
|
Database.insert(
|
||||||
|
Format(
|
||||||
|
songId = mediaId,
|
||||||
|
itag = format.itag,
|
||||||
|
mimeType = format.mimeType,
|
||||||
|
bitrate = format.bitrate,
|
||||||
|
loudnessDb = response.playerConfig?.audioConfig?.normalizedLoudnessDb,
|
||||||
|
contentLength = format.contentLength,
|
||||||
|
lastModified = format.lastModified
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
format = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var volume by remember {
|
var volume by remember {
|
||||||
mutableStateOf(binder.player.volume)
|
mutableStateOf(binder.player.volume)
|
||||||
|
@ -194,47 +221,6 @@ fun StatsForNerds(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format != null && format?.itag == null) {
|
|
||||||
BasicText(
|
|
||||||
text = "FETCH MISSING DATA",
|
|
||||||
style = typography.xxs.medium.color(colorPalette.onOverlay),
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable(
|
|
||||||
onClick = {
|
|
||||||
query {
|
|
||||||
runBlocking(Dispatchers.IO) {
|
|
||||||
Innertube
|
|
||||||
.player(PlayerBody(videoId = mediaId))
|
|
||||||
?.map { response ->
|
|
||||||
response.streamingData?.adaptiveFormats
|
|
||||||
?.findLast { format ->
|
|
||||||
format.itag == 251 || format.itag == 140
|
|
||||||
}
|
|
||||||
?.let { format ->
|
|
||||||
Format(
|
|
||||||
songId = mediaId,
|
|
||||||
itag = format.itag,
|
|
||||||
mimeType = format.mimeType,
|
|
||||||
bitrate = format.bitrate,
|
|
||||||
loudnessDb = response.playerConfig?.audioConfig?.loudnessDb
|
|
||||||
?.toFloat()
|
|
||||||
?.plus(7),
|
|
||||||
contentLength = format.contentLength,
|
|
||||||
lastModified = format.lastModified
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?.getOrNull()
|
|
||||||
?.let(Database::insert)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
|
||||||
.align(Alignment.BottomEnd)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,21 @@ data class PlayerResponse(
|
||||||
) {
|
) {
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AudioConfig(
|
data class AudioConfig(
|
||||||
val loudnessDb: Double?
|
private val loudnessDb: Double?
|
||||||
)
|
) {
|
||||||
|
// For music clients only
|
||||||
|
val normalizedLoudnessDb: Float?
|
||||||
|
get() = loudnessDb?.plus(7)?.toFloat()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class StreamingData(
|
data class StreamingData(
|
||||||
val adaptiveFormats: List<AdaptiveFormat>?
|
val adaptiveFormats: List<AdaptiveFormat>?
|
||||||
) {
|
) {
|
||||||
|
val highestQualityFormat: AdaptiveFormat?
|
||||||
|
get() = adaptiveFormats?.findLast { it.itag == 251 || it.itag == 140 }
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AdaptiveFormat(
|
data class AdaptiveFormat(
|
||||||
val itag: Int,
|
val itag: Int,
|
||||||
|
|
Loading…
Reference in a new issue