Refactor AudioPlayer to use an AudioPlayerRateManager protocol for managing rate/defaultRate state management. Implements a LegacyAudioPlayerRateManager implementation with existing (pre-iOS 16) behavior.

This commit is contained in:
Marke Hallowell 2024-04-14 11:45:03 -07:00
parent bcb239efd1
commit edb25f5bcd
5 changed files with 121 additions and 36 deletions

View file

@ -0,0 +1,84 @@
//
// LegacyAudioPlayerRateManager.swift
// Audiobookshelf
//
// Created by Marke Hallowell on 4/14/24.
//
import Foundation
import AVFoundation
class LegacyAudioPlayerRateManager: NSObject, AudioPlayerRateManager {
internal let logger = AppLogger(category: "AudioPlayer")
internal var audioPlayer: AVPlayer
internal var managerContext = 0
// MARK: - AudioPlayerRateManager
public private(set) var defaultRate: Float
public private(set) var rate: Float
public var rateChangedCompletion: () -> Void
public var defaultRateChangedCompletion: () -> Void
required init(audioPlayer: AVPlayer, defaultRate: Float) {
self.rate = 0.0
self.defaultRate = defaultRate
self.audioPlayer = audioPlayer
self.rateChangedCompletion = {}
self.defaultRateChangedCompletion = {}
super.init()
self.audioPlayer.addObserver(self, forKeyPath: #keyPath(AVPlayer.rate), options: .new, context: &managerContext)
}
public func setPlaybackRate(_ rate: Float) {
self.handlePlaybackRateChange(rate, observed: false)
}
public func handlePlayEvent() {
DispatchQueue.runOnMainQueue {
self.audioPlayer.rate = self.defaultRate
}
}
// MARK: - Destructor
public func destroy() {
// Remove Observer
self.audioPlayer.removeObserver(self, forKeyPath: #keyPath(AVPlayer.rate), context: &managerContext)
}
// MARK: - Internal
internal func handlePlaybackRateChange(_ rate: Float, observed: Bool = false) {
let playbackSpeedChanged = rate > 0.0 && rate != self.defaultRate && !(observed && rate == 1)
if self.audioPlayer.rate != rate {
logger.log("setPlaybakRate rate changed from \(self.audioPlayer.rate) to \(rate)")
DispatchQueue.runOnMainQueue {
self.audioPlayer.rate = rate
}
}
self.rate = rate
self.rateChangedCompletion()
if playbackSpeedChanged {
self.defaultRate = rate
self.defaultRateChangedCompletion()
}
}
// MARK: - Observer
public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &managerContext {
if keyPath == #keyPath(AVPlayer.rate) {
logger.log("playerContext observer player rate")
self.handlePlaybackRateChange(change?[.newKey] as? Float ?? 1.0, observed: true)
}
} else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
}
}