feat: default lang and mpv audio track switching

This commit is contained in:
ned
2025-06-01 21:10:46 +02:00
parent 2a597ab3cb
commit 2461a33feb
7 changed files with 216 additions and 12 deletions

View File

@@ -19,6 +19,7 @@ struct ControlsOverlay: View {
case increaseRate
case decreaseRate
case captions
case audioTrack
}
@FocusState private var focusedField: Field?
@@ -60,6 +61,15 @@ struct ControlsOverlay: View {
#endif
}
if !player.availableAudioTracks.isEmpty {
Section(header: controlsHeader("Audio Track".localized())) {
audioTrackButton
#if os(tvOS)
.focused($focusedField, equals: .audioTrack)
#endif
}
}
Section(header: controlsHeader("Stream & Player".localized())) {
qualityButton
#if os(tvOS)
@@ -438,6 +448,46 @@ struct ControlsOverlay: View {
}
)
}
@ViewBuilder private var audioTrackButton: some View {
#if os(macOS)
audioTrackPicker
.labelsHidden()
.frame(maxWidth: 300)
#elseif os(iOS)
Menu {
audioTrackPicker
} label: {
Text(player.availableAudioTracks[player.selectedAudioTrackIndex].displayLanguage)
.frame(maxWidth: 240, alignment: .trailing)
}
.transaction { t in t.animation = .none }
.buttonStyle(.plain)
.foregroundColor(.accentColor)
.frame(maxWidth: 240, alignment: .trailing)
.frame(height: 40)
#else
ControlsOverlayButton(focusedField: $focusedField, field: .audioTrack) {
Text(player.availableAudioTracks[player.selectedAudioTrackIndex].displayLanguage)
.frame(maxWidth: 320)
}
.contextMenu {
ForEach(Array(player.availableAudioTracks.enumerated()), id: \.offset) { index, track in
Button(track.description) { player.selectedAudioTrackIndex = index }
}
Button("Cancel", role: .cancel) {}
}
#endif
}
private var audioTrackPicker: some View {
Picker("", selection: $player.selectedAudioTrackIndex) {
ForEach(Array(player.availableAudioTracks.enumerated()), id: \.offset) { index, track in
Text(track.description).tag(index)
}
}
.transaction { t in t.animation = .none }
}
}
struct ControlsOverlay_Previews: PreviewProvider {

View File

@@ -22,6 +22,7 @@ struct PlaybackSettings: View {
case increaseRate
case decreaseRate
case captions
case audioTrack
}
@FocusState private var focusedField: Field?
@@ -112,6 +113,17 @@ struct PlaybackSettings: View {
#endif
}
if !player.availableAudioTracks.isEmpty {
HStack {
controlsHeader("Audio Track".localized())
Spacer()
audioTrackButton
#if os(tvOS)
.focused($focusedField, equals: .audioTrack)
#endif
}
}
HStack(spacing: 8) {
controlsHeader("Backend".localized())
Spacer()
@@ -453,6 +465,46 @@ struct PlaybackSettings: View {
}
.disabled(captions.isEmpty)
}
@ViewBuilder private var audioTrackButton: some View {
#if os(macOS)
audioTrackPicker
.labelsHidden()
.frame(maxWidth: 300)
#elseif os(iOS)
Menu {
audioTrackPicker
} label: {
Text(player.availableAudioTracks[player.selectedAudioTrackIndex].displayLanguage)
.frame(maxWidth: 240, alignment: .trailing)
}
.transaction { t in t.animation = .none }
.buttonStyle(.plain)
.foregroundColor(.accentColor)
.frame(maxWidth: 240, alignment: .trailing)
.frame(height: 40)
#else
ControlsOverlayButton(focusedField: $focusedField, field: .audioTrack) {
Text(player.availableAudioTracks[player.selectedAudioTrackIndex].displayLanguage)
.frame(maxWidth: 320)
}
.contextMenu {
ForEach(Array(player.availableAudioTracks.enumerated()), id: \.offset) { index, track in
Button(track.description) { player.selectedAudioTrackIndex = index }
}
Button("Cancel", role: .cancel) {}
}
#endif
}
private var audioTrackPicker: some View {
Picker("", selection: $player.selectedAudioTrackIndex) {
ForEach(Array(player.availableAudioTracks.enumerated()), id: \.offset) { index, track in
Text(track.description).tag(index)
}
}
.transaction { t in t.animation = .none }
}
}
struct PlaybackSettings_Previews: PreviewProvider {