From 1a22ac71be6f499bfe2b04a43967cd828f28fa8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toni=20F=C3=B6rster?= Date: Thu, 29 Aug 2024 15:09:16 +0200 Subject: [PATCH] move AVAudioSession configuration to AppDelegate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Toni Förster --- Model/Player/Backends/AVPlayerBackend.swift | 29 ++++++++++++++++----- Model/Player/Backends/MPVBackend.swift | 15 ----------- iOS/AppDelegate.swift | 19 ++++++++++++-- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/Model/Player/Backends/AVPlayerBackend.swift b/Model/Player/Backends/AVPlayerBackend.swift index 89ccce7d..f1335947 100644 --- a/Model/Player/Backends/AVPlayerBackend.swift +++ b/Model/Player/Backends/AVPlayerBackend.swift @@ -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 { @@ -342,11 +362,8 @@ final class AVPlayerBackend: PlayerBackend { self.asset = nil } - let startPlaying = { - #if !os(macOS) - try? AVAudioSession.sharedInstance().setActive(true) - #endif + let startPlaying = { self.setRate(self.model.currentRate) guard let item = self.model.playerItem, self.isAutoplaying(item) else { return } @@ -779,7 +796,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") } } } diff --git a/Model/Player/Backends/MPVBackend.swift b/Model/Player/Backends/MPVBackend.swift index daf2c51f..981d416e 100644 --- a/Model/Player/Backends/MPVBackend.swift +++ b/Model/Player/Backends/MPVBackend.swift @@ -245,21 +245,6 @@ final class MPVBackend: PlayerBackend { } let startPlaying = { - #if !os(macOS) - do { - try AVAudioSession.sharedInstance().setActive(true) - - NotificationCenter.default.addObserver( - self, - selector: #selector(self.handleAudioSessionInterruption(_:)), - name: AVAudioSession.interruptionNotification, - object: nil - ) - } catch { - self.logger.error("Error setting up audio session: \(error)") - } - #endif - DispatchQueue.main.async { [weak self] in guard let self else { return diff --git a/iOS/AppDelegate.swift b/iOS/AppDelegate.swift index c3247e72..df3bddf0 100644 --- a/iOS/AppDelegate.swift +++ b/iOS/AppDelegate.swift @@ -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,23 @@ 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) + try AVAudioSession.sharedInstance().setActive(true) + } catch { + logger.error("Failed to set audio session category: \(error)") + } + + // Begin receiving remote control events + UIApplication.shared.beginReceivingRemoteControlEvents() #endif + return true }