mirror of
https://github.com/yattee/yattee.git
synced 2026-08-06 07:11:28 +00:00
Add embedded audio/subtitle track selection for multi-track files
Files with multiple embedded tracks (e.g. MKV from media sources or downloads) previously exposed none of them: mpv's track-list was never read, aid was never set, and sid was only ever no/auto. The quality selector showed no Audio or Subtitles tab for such files. MPVClient now observes track-list/aid/sid and delivers a coalesced, leniently decoded [MPVTrack] snapshot; selection state is derived from the reported "selected" flags. Embedded tracks are switched live via aid/sid (no reload), surfaced in the existing Audio/Subtitles sections alongside external captions on iOS, tvOS and macOS. External sub-add/ audio-add tracks are filtered out to avoid double-listing. User picks are sticky across same-video reloads (quality switch, audio mode, retries) and preferred audio/subtitle languages auto-select a matching embedded track once per load, with external captions taking precedence.
This commit is contained in:
@@ -414,6 +414,83 @@ struct CaptionRowView: View {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Embedded Track Row
|
||||
|
||||
/// Row view for embedded (in-container) audio/subtitle tracks reported by mpv.
|
||||
struct EmbeddedTrackRowView: View {
|
||||
let track: MPVTrack
|
||||
let isSelected: Bool
|
||||
let isPreferred: Bool
|
||||
let showAdvancedDetails: Bool
|
||||
let onTap: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Button(action: onTap) {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
titleRow
|
||||
if showAdvancedDetails, let detail = track.detailText {
|
||||
Text(detail)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
if isSelected {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundStyle(.tint)
|
||||
}
|
||||
}
|
||||
.frame(minHeight: showAdvancedDetails ? nil : 36)
|
||||
#if os(tvOS)
|
||||
.padding(.vertical, tvRowVerticalPadding)
|
||||
.padding(.horizontal, tvRowHorizontalPadding)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
#endif
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
#if os(tvOS)
|
||||
.buttonStyle(TVSettingsRowButtonStyle())
|
||||
#else
|
||||
.buttonStyle(.plain)
|
||||
#endif
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var titleRow: some View {
|
||||
HStack(spacing: 6) {
|
||||
if isPreferred {
|
||||
Image(systemName: "star.fill")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.orange)
|
||||
}
|
||||
|
||||
Text(track.displayName)
|
||||
.font(.headline)
|
||||
|
||||
if track.isDefault {
|
||||
badge(String(localized: "player.track.default"))
|
||||
}
|
||||
|
||||
if track.isForced {
|
||||
badge(String(localized: "player.track.forced"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func badge(_ text: String) -> some View {
|
||||
Text(text)
|
||||
.font(.caption2)
|
||||
.padding(.horizontal, 6)
|
||||
.padding(.vertical, 2)
|
||||
.background(Color.gray.opacity(0.2))
|
||||
.foregroundStyle(.secondary)
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
#Preview("Adaptive Stream Row") {
|
||||
|
||||
Reference in New Issue
Block a user