mirror of
				https://github.com/yattee/yattee.git
				synced 2025-10-30 12:11:59 +00:00 
			
		
		
		
	Merge pull request #765 from stonerl/partial-fix-for-503
Update now playing info when using system controls – Partial fix for 503
This commit is contained in:
		| @@ -102,7 +102,7 @@ final class AVPlayerBackend: PlayerBackend { | ||||
|  | ||||
|     private var frequentTimeObserver: Any? | ||||
|     private var infrequentTimeObserver: Any? | ||||
|     private var playerTimeControlStatusObserver: Any? | ||||
|     private var playerTimeControlStatusObserver: NSKeyValueObservation? | ||||
|  | ||||
|     private var statusObservation: NSKeyValueObservation? | ||||
|  | ||||
| @@ -119,6 +119,26 @@ final class AVPlayerBackend: PlayerBackend { | ||||
|         #if os(iOS) | ||||
|             controller.player = avPlayer | ||||
|         #endif | ||||
|         logger.info("AVPlayerBackend initialized.") | ||||
|     } | ||||
|  | ||||
|     deinit { | ||||
|         // Invalidate any observers to avoid memory leaks | ||||
|         statusObservation?.invalidate() | ||||
|         playerTimeControlStatusObserver?.invalidate() | ||||
|  | ||||
|         // Remove any time observers added to AVPlayer | ||||
|         if let frequentObserver = frequentTimeObserver { | ||||
|             avPlayer.removeTimeObserver(frequentObserver) | ||||
|         } | ||||
|         if let infrequentObserver = infrequentTimeObserver { | ||||
|             avPlayer.removeTimeObserver(infrequentObserver) | ||||
|         } | ||||
|  | ||||
|         // Remove notification observers | ||||
|         removeItemDidPlayToEndTimeObserver() | ||||
|  | ||||
|         logger.info("AVPlayerBackend deinitialized.") | ||||
|     } | ||||
|  | ||||
|     func canPlay(_ stream: Stream) -> Bool { | ||||
| @@ -779,7 +799,7 @@ final class AVPlayerBackend: PlayerBackend { | ||||
|                     opened = true | ||||
|                     controller.startPictureInPicture() | ||||
|                 } else { | ||||
|                     print("PiP not possible, waited \(delay) seconds") | ||||
|                     self.logger.info("PiP not possible, waited \(delay) seconds") | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -881,26 +881,29 @@ final class PlayerModel: ObservableObject { | ||||
|     } | ||||
|  | ||||
|     func updateRemoteCommandCenter() { | ||||
|         let skipForwardCommand = MPRemoteCommandCenter.shared().skipForwardCommand | ||||
|         let skipBackwardCommand = MPRemoteCommandCenter.shared().skipBackwardCommand | ||||
|         let previousTrackCommand = MPRemoteCommandCenter.shared().previousTrackCommand | ||||
|         let nextTrackCommand = MPRemoteCommandCenter.shared().nextTrackCommand | ||||
|         let commandCenter = MPRemoteCommandCenter.shared() | ||||
|         let skipForwardCommand = commandCenter.skipForwardCommand | ||||
|         let skipBackwardCommand = commandCenter.skipBackwardCommand | ||||
|         let previousTrackCommand = commandCenter.previousTrackCommand | ||||
|         let nextTrackCommand = commandCenter.nextTrackCommand | ||||
|  | ||||
|         if !remoteCommandCenterConfigured { | ||||
|             remoteCommandCenterConfigured = true | ||||
|  | ||||
|             #if !os(macOS) | ||||
|                 try? AVAudioSession.sharedInstance().setCategory( | ||||
|                     .playback, | ||||
|                     mode: .moviePlayback | ||||
|                 ) | ||||
|  | ||||
|                 UIApplication.shared.beginReceivingRemoteControlEvents() | ||||
|             #endif | ||||
|  | ||||
|             let interval = TimeInterval(systemControlsSeekDuration) ?? 10 | ||||
|             let preferredIntervals = [NSNumber(value: interval)] | ||||
|  | ||||
|             // Remove existing targets to avoid duplicates | ||||
|             skipForwardCommand.removeTarget(nil) | ||||
|             skipBackwardCommand.removeTarget(nil) | ||||
|             previousTrackCommand.removeTarget(nil) | ||||
|             nextTrackCommand.removeTarget(nil) | ||||
|             commandCenter.playCommand.removeTarget(nil) | ||||
|             commandCenter.pauseCommand.removeTarget(nil) | ||||
|             commandCenter.togglePlayPauseCommand.removeTarget(nil) | ||||
|             commandCenter.changePlaybackPositionCommand.removeTarget(nil) | ||||
|  | ||||
|             // Re-add targets for handling commands | ||||
|             skipForwardCommand.preferredIntervals = preferredIntervals | ||||
|             skipBackwardCommand.preferredIntervals = preferredIntervals | ||||
|  | ||||
| @@ -924,22 +927,22 @@ final class PlayerModel: ObservableObject { | ||||
|                 return .success | ||||
|             } | ||||
|  | ||||
|             MPRemoteCommandCenter.shared().playCommand.addTarget { [weak self] _ in | ||||
|             commandCenter.playCommand.addTarget { [weak self] _ in | ||||
|                 self?.play() | ||||
|                 return .success | ||||
|             } | ||||
|  | ||||
|             MPRemoteCommandCenter.shared().pauseCommand.addTarget { [weak self] _ in | ||||
|             commandCenter.pauseCommand.addTarget { [weak self] _ in | ||||
|                 self?.pause() | ||||
|                 return .success | ||||
|             } | ||||
|  | ||||
|             MPRemoteCommandCenter.shared().togglePlayPauseCommand.addTarget { [weak self] _ in | ||||
|             commandCenter.togglePlayPauseCommand.addTarget { [weak self] _ in | ||||
|                 self?.togglePlay() | ||||
|                 return .success | ||||
|             } | ||||
|  | ||||
|             MPRemoteCommandCenter.shared().changePlaybackPositionCommand.addTarget { [weak self] remoteEvent in | ||||
|             commandCenter.changePlaybackPositionCommand.addTarget { [weak self] remoteEvent in | ||||
|                 guard let event = remoteEvent as? MPChangePlaybackPositionCommandEvent else { return .commandFailed } | ||||
|  | ||||
|                 self?.backend.seek(to: event.positionTime, seekType: .userInteracted) | ||||
| @@ -1038,18 +1041,22 @@ final class PlayerModel: ObservableObject { | ||||
|             guard activeBackend == .mpv else { return } | ||||
|         #endif | ||||
|  | ||||
|         #if os(iOS) | ||||
|             if activeBackend == .appleAVPlayer, avPlayerUsesSystemControls { | ||||
|                 return | ||||
|             } | ||||
|         #endif | ||||
|  | ||||
|         guard let video = currentItem?.video else { | ||||
|             MPNowPlayingInfoCenter.default().nowPlayingInfo = .none | ||||
|             return | ||||
|         } | ||||
|  | ||||
|         let currentTime = (backend.currentTime?.seconds.isFinite ?? false) ? backend.currentTime!.seconds : 0 | ||||
|  | ||||
|         // Determine the media type based on musicMode | ||||
|         let mediaType: NSNumber | ||||
|         if musicMode { | ||||
|             mediaType = MPMediaType.anyAudio.rawValue as NSNumber | ||||
|         } else { | ||||
|             mediaType = MPMediaType.anyVideo.rawValue as NSNumber | ||||
|         } | ||||
|  | ||||
|         // Prepare the Now Playing info dictionary | ||||
|         var nowPlayingInfo: [String: AnyObject] = [ | ||||
|             MPMediaItemPropertyTitle: video.displayTitle as AnyObject, | ||||
|             MPMediaItemPropertyArtist: video.displayAuthor as AnyObject, | ||||
| @@ -1057,7 +1064,7 @@ final class PlayerModel: ObservableObject { | ||||
|             MPNowPlayingInfoPropertyElapsedPlaybackTime: currentTime as AnyObject, | ||||
|             MPNowPlayingInfoPropertyPlaybackQueueCount: queue.count as AnyObject, | ||||
|             MPNowPlayingInfoPropertyPlaybackQueueIndex: 1 as AnyObject, | ||||
|             MPMediaItemPropertyMediaType: MPMediaType.anyVideo.rawValue as AnyObject | ||||
|             MPMediaItemPropertyMediaType: mediaType | ||||
|         ] | ||||
|  | ||||
|         if !currentArtwork.isNil { | ||||
| @@ -1261,7 +1268,7 @@ final class PlayerModel: ObservableObject { | ||||
|         } | ||||
|  | ||||
|         private func destroyKeyPressMonitor() { | ||||
|             if let keyPressMonitor = keyPressMonitor { | ||||
|             if let keyPressMonitor { | ||||
|                 NSEvent.removeMonitor(keyPressMonitor) | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,9 +1,12 @@ | ||||
| import AVFoundation | ||||
| import Foundation | ||||
| import Logging | ||||
| import UIKit | ||||
|  | ||||
| final class AppDelegate: UIResponder, UIApplicationDelegate { | ||||
|     var orientationLock = UIInterfaceOrientationMask.all | ||||
|  | ||||
|     private var logger = Logger(label: "stream.yattee.app.delegalate") | ||||
|     private(set) static var instance: AppDelegate! | ||||
|  | ||||
|     func application(_: UIApplication, supportedInterfaceOrientationsFor _: UIWindow?) -> UIInterfaceOrientationMask { | ||||
| @@ -12,11 +15,22 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { | ||||
|  | ||||
|     func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { // swiftlint:disable:this discouraged_optional_collection | ||||
|         Self.instance = self | ||||
|         #if os(iOS) | ||||
|             UIViewController.swizzleHomeIndicatorProperty() | ||||
|  | ||||
|         #if !os(macOS) | ||||
|             UIViewController.swizzleHomeIndicatorProperty() | ||||
|             OrientationTracker.shared.startDeviceOrientationTracking() | ||||
|  | ||||
|             // Configure the audio session for playback | ||||
|             do { | ||||
|                 try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback) | ||||
|             } catch { | ||||
|                 logger.error("Failed to set audio session category: \(error)") | ||||
|             } | ||||
|  | ||||
|             // Begin receiving remote control events | ||||
|             UIApplication.shared.beginReceivingRemoteControlEvents() | ||||
|         #endif | ||||
|  | ||||
|         return true | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Arkadiusz Fal
					Arkadiusz Fal