@@ -21,91 +21,92 @@ import androidx.compose.ui.unit.sp
2121import androidx.media3.common.C
2222import androidx.media3.common.TrackGroup
2323import androidx.media3.common.TrackSelectionOverride
24- import androidx.media3.common.Tracks
24+ import androidx.media3.common.util.UnstableApi
2525import androidx.media3.exoplayer.ExoPlayer
2626import com.donut.mixfile.ui.component.common.MixDialogBuilder
2727import com.donut.mixfile.ui.component.common.SingleSelectItemList
28+ import java.util.Locale
2829
29- object TrackUtils {
30- /* *
31- * 获取格式化后的轨道列表,处理重复 Label
32- */
33- fun getFormattedTracks (
34- groups : List <Tracks .Group >,
35- defaultPrefix : String = "轨道"
36- ): List <TrackInfo > {
37- val options = mutableListOf<TrackInfo >()
38- val labelCounter = mutableMapOf<String , Int >()
39-
40- groups.forEach { group ->
41- for (i in 0 until group.length) {
42- val format = group.getTrackFormat(i)
43- val baseLabel = format.label ? : format.language ? : defaultPrefix
44-
45- val count = labelCounter.getOrDefault(baseLabel, 0 ) + 1
46- labelCounter[baseLabel] = count
47- val finalLabel = if (count > 1 ) " $baseLabel -$count " else baseLabel
48-
49- options.add(
50- TrackInfo (
51- finalLabel,
52- group.mediaTrackGroup,
53- i,
54- group.isSelected && group.isTrackSelected(i)
55- )
56- )
57- }
58- }
59- return options
60- }
61-
62- data class TrackInfo (
63- val label : String ,
64- val group : TrackGroup ,
65- val index : Int ,
66- val isSelected : Boolean
67- )
68- }
6930
7031/* *
7132 * 显示字幕/音轨选择弹窗
7233 */
34+ @androidx.annotation.OptIn (UnstableApi ::class )
7335fun showTrackSelector (
7436 title : String ,
7537 player : ExoPlayer ,
7638 trackType : @C.TrackType Int ,
7739 colorScheme : ColorScheme ,
7840 hasDisableOption : Boolean = false
7941) {
80- // 只保留指定类型的 track group
42+ // 1. 获取所有轨道组并提取规范化信息
8143 val groups = player.currentTracks.groups.filter { it.type == trackType }
82- val trackInfos = TrackUtils .getFormattedTracks(
83- groups,
84- if (trackType == C .TRACK_TYPE_TEXT ) " 字幕" else " 音轨"
44+
45+ // 内部数据类,用于解耦逻辑
46+ data class TrackDisplayInfo (
47+ val label : String ,
48+ val group : TrackGroup ,
49+ val index : Int ,
50+ val isSelected : Boolean
8551 )
8652
87- // 构建选项列表
53+ var trackIndex = 1
54+ val trackInfos = groups.flatMap { group ->
55+ val trackGroup = group.mediaTrackGroup
56+ List (trackGroup.length) { i ->
57+ val format = trackGroup.getFormat(i)
58+ val langLabel = format.language?.let { lang ->
59+ val locale = Locale .forLanguageTag(lang)
60+
61+ locale.getDisplayName(Locale .getDefault()).ifBlank { format.language }
62+ } ? : " 未知"
63+
64+
65+ val displayLabel = " ${trackIndex} ${langLabel} " .let {
66+ if (format.label != null ) {
67+ it + " - ${format.label} "
68+ } else it
69+ }
70+ trackIndex++
71+
72+
73+ TrackDisplayInfo (
74+ label = displayLabel,
75+ group = trackGroup,
76+ index = i,
77+ isSelected = group.isTrackSelected(i)
78+ )
79+ }
80+ }
81+
82+ // 2. 构建 UI 选项列表
83+ val disableLabel = if (trackType == C .TRACK_TYPE_TEXT ) " 关闭字幕" else " 禁用音轨"
8884 val options = buildList {
89- if (hasDisableOption) add(" 关闭 " )
85+ if (hasDisableOption) add(disableLabel )
9086 addAll(trackInfos.map { it.label })
9187 }
9288
93- // 获取当前选中的 label
94- val currentLabel = trackInfos.firstOrNull { it.isSelected }?.label
95- ? : if (hasDisableOption) " 关闭" else options.firstOrNull().orEmpty()
89+ val currentSelectedLabel = trackInfos.firstOrNull { it.isSelected }?.label ? : disableLabel
9690
9791 MixDialogBuilder (title, colorScheme = colorScheme).apply {
9892 setContent {
99- SingleSelectItemList (options, currentOption = currentLabel) { selected ->
100- val builder = player.trackSelectionParameters.buildUpon()
101- if (selected == " 关闭" ) {
102- builder.setTrackTypeDisabled(trackType, true )
93+ SingleSelectItemList (options, currentOption = currentSelectedLabel) { selected ->
94+ val paramsBuilder = player.trackSelectionParameters.buildUpon()
95+
96+ if (selected == disableLabel) {
97+ paramsBuilder.setTrackTypeDisabled(trackType, true )
10398 } else {
104- val info = trackInfos.first { it.label == selected }
105- builder.setTrackTypeDisabled(trackType, false )
106- .setOverrideForType(TrackSelectionOverride (info.group, info.index))
99+ val info = trackInfos.firstOrNull { it.label == selected }
100+ info?.let {
101+ paramsBuilder
102+ .setTrackTypeDisabled(trackType, false )
103+ // 清除该类型之前的覆盖设置,确保新设置生效
104+ .clearOverridesOfType(trackType)
105+ .addOverride(TrackSelectionOverride (it.group, it.index))
106+ }
107107 }
108- player.trackSelectionParameters = builder.build()
108+
109+ player.trackSelectionParameters = paramsBuilder.build()
109110 closeDialog()
110111 }
111112 }
0 commit comments