mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-24 03:36:51 +00:00
feat: enhance track label formatting for audio, subtitles, and video
This commit is contained in:
@@ -7,6 +7,7 @@ import androidx.media3.common.Tracks
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import hu.bbara.purefin.player.model.TrackOption
|
||||
import hu.bbara.purefin.player.model.TrackType
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
data class TrackSelectionState(
|
||||
@@ -35,10 +36,7 @@ class TrackMapper @Inject constructor() {
|
||||
repeat(group.length) { trackIndex ->
|
||||
val format = group.getTrackFormat(trackIndex)
|
||||
val id = "a_${groupIndex}_${trackIndex}"
|
||||
val label = format.label
|
||||
?: format.language
|
||||
?: "${format.channelCount}ch"
|
||||
?: "Audio ${trackIndex}"
|
||||
val label = formatAudioLabel(format, trackIndex)
|
||||
val option = TrackOption(
|
||||
id = id,
|
||||
label = label,
|
||||
@@ -60,10 +58,8 @@ class TrackMapper @Inject constructor() {
|
||||
repeat(group.length) { trackIndex ->
|
||||
val format = group.getTrackFormat(trackIndex)
|
||||
val id = "t_${groupIndex}_${trackIndex}"
|
||||
val label = format.label
|
||||
?: format.language
|
||||
?: "Subtitle ${trackIndex}"
|
||||
val isForced = (format.selectionFlags and C.SELECTION_FLAG_FORCED) != 0
|
||||
val label = formatTextLabel(format, trackIndex, isForced)
|
||||
val option = TrackOption(
|
||||
id = id,
|
||||
label = label,
|
||||
@@ -86,8 +82,7 @@ class TrackMapper @Inject constructor() {
|
||||
repeat(group.length) { trackIndex ->
|
||||
val format = group.getTrackFormat(trackIndex)
|
||||
val id = "v_${groupIndex}_${trackIndex}"
|
||||
val res = if (format.height != Format.NO_VALUE) "${format.height}p" else null
|
||||
val label = res ?: format.label ?: "Video ${trackIndex}"
|
||||
val label = formatVideoLabel(format, trackIndex)
|
||||
val option = TrackOption(
|
||||
id = id,
|
||||
label = label,
|
||||
@@ -134,4 +129,122 @@ class TrackMapper @Inject constructor() {
|
||||
selectedVideoTrackId = selectedVideo
|
||||
)
|
||||
}
|
||||
|
||||
private fun formatAudioLabel(format: Format, trackIndex: Int): String {
|
||||
val details = listOfNotNull(
|
||||
displayLanguage(format.language),
|
||||
audioCodec(format),
|
||||
channelLabel(format.channelCount)
|
||||
).joinToString(" ")
|
||||
|
||||
return labelWithDetails(
|
||||
title = format.label,
|
||||
details = details,
|
||||
fallback = "Audio ${trackIndex + 1}"
|
||||
)
|
||||
}
|
||||
|
||||
private fun formatTextLabel(format: Format, trackIndex: Int, isForced: Boolean): String {
|
||||
val details = listOfNotNull(
|
||||
displayLanguage(format.language),
|
||||
subtitleCodec(format),
|
||||
"Forced".takeIf { isForced }
|
||||
).joinToString(" ")
|
||||
|
||||
return labelWithDetails(
|
||||
title = format.label,
|
||||
details = details,
|
||||
fallback = "Subtitle ${trackIndex + 1}"
|
||||
)
|
||||
}
|
||||
|
||||
private fun formatVideoLabel(format: Format, trackIndex: Int): String {
|
||||
val details = if (format.height != Format.NO_VALUE && format.height > 0) {
|
||||
"${format.height}p"
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return labelWithDetails(
|
||||
title = format.label,
|
||||
details = details,
|
||||
fallback = "Video ${trackIndex + 1}"
|
||||
)
|
||||
}
|
||||
|
||||
private fun labelWithDetails(title: String?, details: String?, fallback: String): String {
|
||||
val cleanTitle = title?.trim()?.takeIf { it.isNotEmpty() }
|
||||
val cleanDetails = details?.trim()?.takeIf { it.isNotEmpty() }
|
||||
|
||||
return when {
|
||||
cleanTitle != null && cleanDetails != null && cleanTitle != cleanDetails ->
|
||||
"$cleanTitle - $cleanDetails"
|
||||
|
||||
cleanTitle != null -> cleanTitle
|
||||
cleanDetails != null -> cleanDetails
|
||||
else -> fallback
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayLanguage(code: String?): String? {
|
||||
val cleanCode = code
|
||||
?.trim()
|
||||
?.takeIf { it.isNotEmpty() && !it.equals("und", ignoreCase = true) }
|
||||
?: return null
|
||||
val locale = Locale.forLanguageTag(cleanCode.replace('_', '-'))
|
||||
val language = locale.getDisplayLanguage(Locale.getDefault())
|
||||
|
||||
return language.takeIf { it.isNotEmpty() && it != cleanCode } ?: cleanCode
|
||||
}
|
||||
|
||||
private fun audioCodec(format: Format): String? {
|
||||
val value = format.codecText()
|
||||
|
||||
return when {
|
||||
value.contains("truehd") -> "TrueHD"
|
||||
value.contains("eac3") || value.contains("e-ac-3") || value.contains("ec-3") ->
|
||||
"Dolby Digital Plus"
|
||||
|
||||
value.contains("ac3") || value.contains("ac-3") -> "Dolby Digital"
|
||||
value.contains("dts") || value.contains("dca") -> "DTS"
|
||||
value.contains("alac") -> "ALAC"
|
||||
value.contains("flac") -> "FLAC"
|
||||
value.contains("opus") -> "Opus"
|
||||
value.contains("vorbis") || value.contains("ogg") -> "Vorbis"
|
||||
value.contains("mp3") || value.contains("mpeg") -> "MP3"
|
||||
value.contains("aac") || value.contains("mp4a") -> "AAC"
|
||||
value.contains("pcm") || value.contains("raw") || value.contains("lpcm") -> "PCM"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun subtitleCodec(format: Format): String? {
|
||||
val value = format.codecText()
|
||||
|
||||
return when {
|
||||
value.contains("subrip") || value.contains("srt") -> "SRT"
|
||||
value.contains("ssa") || value.contains("ass") -> "ASS"
|
||||
value.contains("pgs") || value.contains("pgssub") -> "PGS"
|
||||
value.contains("dvb") -> "DVB"
|
||||
value.contains("dvd") || value.contains("vobsub") -> "DVD"
|
||||
value.contains("vtt") || value.contains("webvtt") -> "VTT"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun Format.codecText(): String = listOfNotNull(
|
||||
sampleMimeType,
|
||||
containerMimeType,
|
||||
codecs
|
||||
).joinToString(" ").lowercase(Locale.US)
|
||||
|
||||
private fun channelLabel(channelCount: Int): String? =
|
||||
when {
|
||||
channelCount == Format.NO_VALUE || channelCount <= 0 -> null
|
||||
channelCount == 1 -> "Mono"
|
||||
channelCount == 2 -> "Stereo"
|
||||
channelCount == 6 -> "5.1"
|
||||
channelCount == 8 -> "7.1"
|
||||
else -> "$channelCount ch"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user