Make format automatically update when stats for nerds are displayed

This commit is contained in:
vfsfitvnm 2022-10-17 14:50:27 +02:00
parent 43fda751b6
commit 192263d95b
4 changed files with 46 additions and 56 deletions

View file

@ -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")

View file

@ -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
) )

View file

@ -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)
)
}
} }
} }
} }

View file

@ -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,