@@ -237,6 +237,7 @@ public final class PUIPlayerView: NSView {
237237 player. addObserver ( self , forKeyPath: #keyPath( AVPlayer . rate) , options: [ . initial, . new] , context: nil )
238238 player. addObserver ( self , forKeyPath: #keyPath( AVPlayer . currentItem. loadedTimeRanges) , options: [ . initial, . new] , context: nil )
239239 player. addObserver ( self , forKeyPath: #keyPath( AVPlayer . currentItem. duration) , options: [ . initial, . new] , context: nil )
240+ player. addObserver ( self , forKeyPath: #keyPath( AVPlayer . currentItem. currentMediaSelection) , options: [ . initial, . new] , context: nil )
240241
241242 asset? . loadValuesAsynchronously ( forKeys: [ " tracks " ] , completionHandler: metadataBecameAvailable)
242243
@@ -259,6 +260,7 @@ public final class PUIPlayerView: NSView {
259260 oldValue. removeObserver ( self , forKeyPath: #keyPath( AVPlayer . volume) )
260261 oldValue. removeObserver ( self , forKeyPath: #keyPath( AVPlayer . currentItem. loadedTimeRanges) )
261262 oldValue. removeObserver ( self , forKeyPath: #keyPath( AVPlayer . currentItem. duration) )
263+ oldValue. removeObserver ( self , forKeyPath: #keyPath( AVPlayer . currentItem. currentMediaSelection) )
262264 }
263265
264266 public override func observeValue( forKeyPath keyPath: String ? , of object: Any ? , change: [ NSKeyValueChangeKey : Any ] ? , context: UnsafeMutableRawPointer ? ) {
@@ -273,6 +275,8 @@ public final class PUIPlayerView: NSView {
273275 self . updatePlayingState ( )
274276 } else if keyPath == #keyPath( AVPlayer . currentItem. duration) {
275277 self . metadataBecameAvailable ( )
278+ } else if keyPath == #keyPath( AVPlayer . currentItem. currentMediaSelection) {
279+ self . updateMediaSelection ( )
276280 } else {
277281 super. observeValue ( forKeyPath: keyPath, of: object, change: change, context: context)
278282 }
@@ -790,10 +794,6 @@ public final class PUIPlayerView: NSView {
790794 }
791795 }
792796
793- @IBAction func showSubtitlesMenu( _ sender: PUIButton ) {
794- // TODO: show subtitles menu
795- }
796-
797797 @IBAction public func togglePlaying( _ sender: Any ? ) {
798798 if isPlaying {
799799 pause ( sender)
@@ -879,6 +879,60 @@ public final class PUIPlayerView: NSView {
879879 }
880880 }
881881
882+ // MARK: - Subtitles
883+
884+ private var subtitlesMenu : NSMenu ?
885+ private var subtitlesGroup : AVMediaSelectionGroup ?
886+
887+ private func updateMediaSelection( ) {
888+ guard let playerItem = player? . currentItem else { return }
889+
890+ guard let subtitlesGroup = playerItem. asset. mediaSelectionGroup ( forMediaCharacteristic: AVMediaCharacteristicLegible) else {
891+ subtitlesButton. isHidden = true
892+ return
893+ }
894+
895+ self . subtitlesGroup = subtitlesGroup
896+
897+ let currentMediaSelection = playerItem. currentMediaSelection
898+
899+ subtitlesButton. isHidden = false
900+
901+ let menu = NSMenu ( )
902+
903+ subtitlesGroup. options. forEach { option in
904+ let item = NSMenuItem ( title: option. displayName, action: #selector( didSelectSubtitleOption ( _: ) ) , keyEquivalent: " " )
905+ item. representedObject = option
906+ item. target = self
907+
908+ menu. addItem ( item)
909+ }
910+
911+ self . subtitlesMenu = menu
912+ }
913+
914+ @objc fileprivate func didSelectSubtitleOption( _ sender: NSMenuItem ) {
915+ guard let subtitlesGroup = self . subtitlesGroup else { return }
916+ guard let option = sender. representedObject as? AVMediaSelectionOption else { return }
917+
918+ // reset all item's states
919+ sender. menu? . items. forEach ( { $0. state = NSOffState } )
920+
921+ if option. extendedLanguageTag == player? . currentItem? . selectedMediaOption ( in: subtitlesGroup) ? . extendedLanguageTag {
922+ player? . currentItem? . select ( nil , in: subtitlesGroup)
923+ sender. state = NSOffState
924+ return
925+ }
926+
927+ player? . currentItem? . select ( option, in: subtitlesGroup)
928+
929+ sender. state = NSOnState
930+ }
931+
932+ @IBAction func showSubtitlesMenu( _ sender: PUIButton ) {
933+ subtitlesMenu? . popUp ( positioning: nil , at: . zero, in: sender)
934+ }
935+
882936 // MARK: - Key commands
883937
884938 private var keyDownEventMonitor : Any ?
0 commit comments