mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-08-29 22:57:16 +02:00
feat: Handle route change notifications
This commit is contained in:
@@ -71,7 +71,7 @@ class AudioPlayer: NSObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Listen to player events
|
// Listen to player events
|
||||||
self.setupInteruptionNotification()
|
self.setupAudioSessionNotifications()
|
||||||
self.audioPlayer.addObserver(self, forKeyPath: #keyPath(AVPlayer.rate), options: .new, context: &playerContext)
|
self.audioPlayer.addObserver(self, forKeyPath: #keyPath(AVPlayer.rate), options: .new, context: &playerContext)
|
||||||
self.audioPlayer.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem), options: .new, context: &playerContext)
|
self.audioPlayer.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem), options: .new, context: &playerContext)
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ class AudioPlayer: NSObject {
|
|||||||
print(error)
|
print(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.removeInteruptionNotification()
|
self.removeAudioSessionNotifications()
|
||||||
DispatchQueue.runOnMainQueue {
|
DispatchQueue.runOnMainQueue {
|
||||||
UIApplication.shared.endReceivingRemoteControlEvents()
|
UIApplication.shared.endReceivingRemoteControlEvents()
|
||||||
}
|
}
|
||||||
@@ -148,12 +148,14 @@ class AudioPlayer: NSObject {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupInteruptionNotification() {
|
private func setupAudioSessionNotifications() {
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(handleInteruption), name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance())
|
NotificationCenter.default.addObserver(self, selector: #selector(handleInteruption), name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance())
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(handleRouteChange), name: AVAudioSession.routeChangeNotification, object: AVAudioSession.sharedInstance())
|
||||||
}
|
}
|
||||||
|
|
||||||
private func removeInteruptionNotification() {
|
private func removeAudioSessionNotifications() {
|
||||||
NotificationCenter.default.removeObserver(self, name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance())
|
NotificationCenter.default.removeObserver(self, name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance())
|
||||||
|
NotificationCenter.default.removeObserver(self, name: AVAudioSession.routeChangeNotification, object: AVAudioSession.sharedInstance())
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupTimeObserver() {
|
private func setupTimeObserver() {
|
||||||
@@ -598,7 +600,7 @@ class AudioPlayer: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - iOS audio interupt notifications
|
// MARK: - iOS audio session notifications
|
||||||
@objc private func handleInteruption(notification: Notification) {
|
@objc private func handleInteruption(notification: Notification) {
|
||||||
guard let userInfo = notification.userInfo,
|
guard let userInfo = notification.userInfo,
|
||||||
let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
|
let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
|
||||||
@@ -617,6 +619,38 @@ class AudioPlayer: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func handleRouteChange(notification: Notification) {
|
||||||
|
guard let userInfo = notification.userInfo,
|
||||||
|
let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
|
||||||
|
let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch reason {
|
||||||
|
case .newDeviceAvailable: // New device found.
|
||||||
|
let session = AVAudioSession.sharedInstance()
|
||||||
|
let headphonesConnected = hasHeadphones(in: session.currentRoute)
|
||||||
|
if headphonesConnected {
|
||||||
|
// We should just let things be, as it's okay to go from speaker to headphones
|
||||||
|
}
|
||||||
|
case .oldDeviceUnavailable: // Old device removed.
|
||||||
|
if let previousRoute = userInfo[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription {
|
||||||
|
let headphonesWereConnected = hasHeadphones(in: previousRoute)
|
||||||
|
if headphonesWereConnected {
|
||||||
|
// Removing headphones we should pause instead of keeping on playing
|
||||||
|
self.pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default: ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func hasHeadphones(in routeDescription: AVAudioSessionRouteDescription) -> Bool {
|
||||||
|
// Filter the outputs to only those with a port type of headphones.
|
||||||
|
return !routeDescription.outputs.filter({$0.portType == .headphones}).isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Now playing
|
// MARK: - Now playing
|
||||||
private func setupRemoteTransportControls() {
|
private func setupRemoteTransportControls() {
|
||||||
DispatchQueue.runOnMainQueue {
|
DispatchQueue.runOnMainQueue {
|
||||||
|
|||||||
Reference in New Issue
Block a user