mirror of
https://github.com/yattee/yattee.git
synced 2026-08-05 23:01: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:
@@ -29,6 +29,15 @@ struct QualitySelectorView: View {
|
||||
let onLoadOnlineStreams: () -> Void
|
||||
let onSwitchToOnlineStream: (Stream, Stream?) -> Void
|
||||
|
||||
/// Embedded (in-container) tracks reported by mpv for the loaded file.
|
||||
let embeddedAudioTracks: [MPVTrack]
|
||||
let embeddedSubtitleTracks: [MPVTrack]
|
||||
let currentEmbeddedAudioTrackID: Int?
|
||||
let currentEmbeddedSubtitleTrackID: Int?
|
||||
let onEmbeddedAudioTrackSelected: (Int) -> Void
|
||||
/// nil = subtitles off
|
||||
let onEmbeddedSubtitleTrackSelected: (Int?) -> Void
|
||||
|
||||
/// Current playback rate
|
||||
var currentRate: PlaybackRate = .x1
|
||||
/// Callback when playback rate changes
|
||||
@@ -100,10 +109,10 @@ struct QualitySelectorView: View {
|
||||
/// Available tabs based on streams
|
||||
var availableTabs: [QualitySelectorTab] {
|
||||
var tabs: [QualitySelectorTab] = [.video]
|
||||
if hasVideoOnlyStreams && !audioStreams.isEmpty {
|
||||
if (hasVideoOnlyStreams && !audioStreams.isEmpty) || embeddedAudioTracks.count > 1 {
|
||||
tabs.append(.audio)
|
||||
}
|
||||
if !captions.isEmpty {
|
||||
if !captions.isEmpty || !embeddedSubtitleTracks.isEmpty {
|
||||
tabs.append(.subtitles)
|
||||
}
|
||||
return tabs
|
||||
@@ -133,7 +142,7 @@ struct QualitySelectorView: View {
|
||||
/// Whether streams are empty (not loading, but no streams available)
|
||||
var hasNoStreams: Bool {
|
||||
if !showTabPicker && initialTab == .subtitles {
|
||||
return !isLoading && captions.isEmpty && !isPlayingDownloadedContent
|
||||
return !isLoading && captions.isEmpty && embeddedSubtitleTracks.isEmpty && !isPlayingDownloadedContent
|
||||
}
|
||||
return !isLoading && streams.isEmpty && !isPlayingDownloadedContent
|
||||
}
|
||||
@@ -168,10 +177,16 @@ struct QualitySelectorView: View {
|
||||
isAudioMode: Bool = false,
|
||||
initialTab: QualitySelectorTab = .video,
|
||||
showTabPicker: Bool = true,
|
||||
embeddedAudioTracks: [MPVTrack] = [],
|
||||
embeddedSubtitleTracks: [MPVTrack] = [],
|
||||
currentEmbeddedAudioTrackID: Int? = nil,
|
||||
currentEmbeddedSubtitleTrackID: Int? = nil,
|
||||
onStreamSelected: @escaping (Stream, Stream?) -> Void,
|
||||
onCaptionSelected: @escaping (Caption?) -> Void = { _ in },
|
||||
onLoadOnlineStreams: @escaping () -> Void = {},
|
||||
onSwitchToOnlineStream: @escaping (Stream, Stream?) -> Void = { _, _ in },
|
||||
onEmbeddedAudioTrackSelected: @escaping (Int) -> Void = { _ in },
|
||||
onEmbeddedSubtitleTrackSelected: @escaping (Int?) -> Void = { _ in },
|
||||
onRateChanged: ((PlaybackRate) -> Void)? = nil,
|
||||
onLockToggled: ((Bool) -> Void)? = nil,
|
||||
onAudioModeToggled: ((Bool) -> Void)? = nil,
|
||||
@@ -191,10 +206,16 @@ struct QualitySelectorView: View {
|
||||
self.currentRate = currentRate
|
||||
self.isControlsLocked = isControlsLocked
|
||||
self.isAudioMode = isAudioMode
|
||||
self.embeddedAudioTracks = embeddedAudioTracks
|
||||
self.embeddedSubtitleTracks = embeddedSubtitleTracks
|
||||
self.currentEmbeddedAudioTrackID = currentEmbeddedAudioTrackID
|
||||
self.currentEmbeddedSubtitleTrackID = currentEmbeddedSubtitleTrackID
|
||||
self.onStreamSelected = onStreamSelected
|
||||
self.onCaptionSelected = onCaptionSelected
|
||||
self.onLoadOnlineStreams = onLoadOnlineStreams
|
||||
self.onSwitchToOnlineStream = onSwitchToOnlineStream
|
||||
self.onEmbeddedAudioTrackSelected = onEmbeddedAudioTrackSelected
|
||||
self.onEmbeddedSubtitleTrackSelected = onEmbeddedSubtitleTrackSelected
|
||||
self.onRateChanged = onRateChanged
|
||||
self.onLockToggled = onLockToggled
|
||||
self.onAudioModeToggled = onAudioModeToggled
|
||||
|
||||
Reference in New Issue
Block a user