mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-19 09:08:26 +02:00
Fix memory leak
This commit is contained in:
parent
836ffddd4f
commit
fb8e6408bb
2 changed files with 30 additions and 23 deletions
|
@ -100,20 +100,21 @@ class AudioPlayer: NSObject {
|
||||||
|
|
||||||
NSLog("Audioplayer ready")
|
NSLog("Audioplayer ready")
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.stopPausedTimer()
|
self.stopPausedTimer()
|
||||||
self.removeSleepTimer()
|
self.removeSleepTimer()
|
||||||
self.removeTimeObserver()
|
self.removeTimeObserver()
|
||||||
self.queueObserver?.invalidate()
|
self.queueObserver?.invalidate()
|
||||||
self.queueItemStatusObserver?.invalidate()
|
self.queueItemStatusObserver?.invalidate()
|
||||||
destroy()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func destroy() {
|
public func destroy() {
|
||||||
// Pause is not synchronous causing this error on below lines:
|
// Pause is not synchronous causing this error on below lines:
|
||||||
// AVAudioSession_iOS.mm:1206 Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session
|
// AVAudioSession_iOS.mm:1206 Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session
|
||||||
// It is related to L79 `AVAudioSession.sharedInstance().setActive(false)`
|
// It is related to L79 `AVAudioSession.sharedInstance().setActive(false)`
|
||||||
pause()
|
self.pause()
|
||||||
audioPlayer.replaceCurrentItem(with: nil)
|
self.audioPlayer.replaceCurrentItem(with: nil)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try AVAudioSession.sharedInstance().setActive(false)
|
try AVAudioSession.sharedInstance().setActive(false)
|
||||||
|
@ -125,6 +126,11 @@ class AudioPlayer: NSObject {
|
||||||
DispatchQueue.runOnMainQueue {
|
DispatchQueue.runOnMainQueue {
|
||||||
UIApplication.shared.endReceivingRemoteControlEvents()
|
UIApplication.shared.endReceivingRemoteControlEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove observers
|
||||||
|
self.audioPlayer.removeObserver(self, forKeyPath: #keyPath(AVPlayer.rate), context: &playerContext)
|
||||||
|
self.audioPlayer.removeObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem), context: &playerContext)
|
||||||
|
|
||||||
NotificationCenter.default.post(name: NSNotification.Name(PlayerEvents.closed.rawValue), object: nil)
|
NotificationCenter.default.post(name: NSNotification.Name(PlayerEvents.closed.rawValue), object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +191,8 @@ class AudioPlayer: NSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupQueueObserver() {
|
private func setupQueueObserver() {
|
||||||
self.queueObserver = self.audioPlayer.observe(\.currentItem, options: [.new]) {_,_ in
|
self.queueObserver = self.audioPlayer.observe(\.currentItem, options: [.new]) { [weak self] _,_ in
|
||||||
|
guard let self = self else { return }
|
||||||
let prevTrackIndex = self.currentTrackIndex
|
let prevTrackIndex = self.currentTrackIndex
|
||||||
self.audioPlayer.currentItem.map { item in
|
self.audioPlayer.currentItem.map { item in
|
||||||
self.currentTrackIndex = self.allPlayerItems.firstIndex(of:item) ?? 0
|
self.currentTrackIndex = self.allPlayerItems.firstIndex(of:item) ?? 0
|
||||||
|
@ -201,8 +208,8 @@ class AudioPlayer: NSObject {
|
||||||
|
|
||||||
// Listen for player item updates
|
// Listen for player item updates
|
||||||
self.queueItemStatusObserver?.invalidate()
|
self.queueItemStatusObserver?.invalidate()
|
||||||
self.queueItemStatusObserver = self.audioPlayer.currentItem?.observe(\.status, options: [.new, .old], changeHandler: { playerItem, change in
|
self.queueItemStatusObserver = self.audioPlayer.currentItem?.observe(\.status, options: [.new, .old], changeHandler: { [weak self] playerItem, change in
|
||||||
self.handleQueueItemStatus(playerItem: playerItem)
|
self?.handleQueueItemStatus(playerItem: playerItem)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Ensure we didn't miss a player item update during initialization
|
// Ensure we didn't miss a player item update during initialization
|
||||||
|
@ -486,59 +493,59 @@ class AudioPlayer: NSObject {
|
||||||
let deviceSettings = Database.shared.getDeviceSettings()
|
let deviceSettings = Database.shared.getDeviceSettings()
|
||||||
|
|
||||||
commandCenter.playCommand.isEnabled = true
|
commandCenter.playCommand.isEnabled = true
|
||||||
commandCenter.playCommand.addTarget { [unowned self] event in
|
commandCenter.playCommand.addTarget { [weak self] event in
|
||||||
play(allowSeekBack: true)
|
self?.play(allowSeekBack: true)
|
||||||
return .success
|
return .success
|
||||||
}
|
}
|
||||||
commandCenter.pauseCommand.isEnabled = true
|
commandCenter.pauseCommand.isEnabled = true
|
||||||
commandCenter.pauseCommand.addTarget { [unowned self] event in
|
commandCenter.pauseCommand.addTarget { [weak self] event in
|
||||||
pause()
|
self?.pause()
|
||||||
return .success
|
return .success
|
||||||
}
|
}
|
||||||
|
|
||||||
commandCenter.skipForwardCommand.isEnabled = true
|
commandCenter.skipForwardCommand.isEnabled = true
|
||||||
commandCenter.skipForwardCommand.preferredIntervals = [NSNumber(value: deviceSettings.jumpForwardTime)]
|
commandCenter.skipForwardCommand.preferredIntervals = [NSNumber(value: deviceSettings.jumpForwardTime)]
|
||||||
commandCenter.skipForwardCommand.addTarget { [unowned self] event in
|
commandCenter.skipForwardCommand.addTarget { [weak self] event in
|
||||||
guard let command = event.command as? MPSkipIntervalCommand else {
|
guard let command = event.command as? MPSkipIntervalCommand else {
|
||||||
return .noSuchContent
|
return .noSuchContent
|
||||||
}
|
}
|
||||||
guard let currentTime = self.getCurrentTime() else {
|
guard let currentTime = self?.getCurrentTime() else {
|
||||||
return .commandFailed
|
return .commandFailed
|
||||||
}
|
}
|
||||||
seek(currentTime + command.preferredIntervals[0].doubleValue, from: "remote")
|
self?.seek(currentTime + command.preferredIntervals[0].doubleValue, from: "remote")
|
||||||
return .success
|
return .success
|
||||||
}
|
}
|
||||||
commandCenter.skipBackwardCommand.isEnabled = true
|
commandCenter.skipBackwardCommand.isEnabled = true
|
||||||
commandCenter.skipBackwardCommand.preferredIntervals = [NSNumber(value: deviceSettings.jumpBackwardsTime)]
|
commandCenter.skipBackwardCommand.preferredIntervals = [NSNumber(value: deviceSettings.jumpBackwardsTime)]
|
||||||
commandCenter.skipBackwardCommand.addTarget { [unowned self] event in
|
commandCenter.skipBackwardCommand.addTarget { [weak self] event in
|
||||||
guard let command = event.command as? MPSkipIntervalCommand else {
|
guard let command = event.command as? MPSkipIntervalCommand else {
|
||||||
return .noSuchContent
|
return .noSuchContent
|
||||||
}
|
}
|
||||||
guard let currentTime = self.getCurrentTime() else {
|
guard let currentTime = self?.getCurrentTime() else {
|
||||||
return .commandFailed
|
return .commandFailed
|
||||||
}
|
}
|
||||||
seek(currentTime - command.preferredIntervals[0].doubleValue, from: "remote")
|
self?.seek(currentTime - command.preferredIntervals[0].doubleValue, from: "remote")
|
||||||
return .success
|
return .success
|
||||||
}
|
}
|
||||||
|
|
||||||
commandCenter.changePlaybackPositionCommand.isEnabled = true
|
commandCenter.changePlaybackPositionCommand.isEnabled = true
|
||||||
commandCenter.changePlaybackPositionCommand.addTarget { event in
|
commandCenter.changePlaybackPositionCommand.addTarget { [weak self] event in
|
||||||
guard let event = event as? MPChangePlaybackPositionCommandEvent else {
|
guard let event = event as? MPChangePlaybackPositionCommandEvent else {
|
||||||
return .noSuchContent
|
return .noSuchContent
|
||||||
}
|
}
|
||||||
|
|
||||||
self.seek(event.positionTime, from: "remote")
|
self?.seek(event.positionTime, from: "remote")
|
||||||
return .success
|
return .success
|
||||||
}
|
}
|
||||||
|
|
||||||
commandCenter.changePlaybackRateCommand.isEnabled = true
|
commandCenter.changePlaybackRateCommand.isEnabled = true
|
||||||
commandCenter.changePlaybackRateCommand.supportedPlaybackRates = [0.5, 0.75, 1.0, 1.25, 1.5, 2]
|
commandCenter.changePlaybackRateCommand.supportedPlaybackRates = [0.5, 0.75, 1.0, 1.25, 1.5, 2]
|
||||||
commandCenter.changePlaybackRateCommand.addTarget { event in
|
commandCenter.changePlaybackRateCommand.addTarget { [weak self] event in
|
||||||
guard let event = event as? MPChangePlaybackRateCommandEvent else {
|
guard let event = event as? MPChangePlaybackRateCommandEvent else {
|
||||||
return .noSuchContent
|
return .noSuchContent
|
||||||
}
|
}
|
||||||
|
|
||||||
self.setPlaybackRate(event.playbackRate)
|
self?.setPlaybackRate(event.playbackRate)
|
||||||
return .success
|
return .success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,9 @@ extension AudioPlayer {
|
||||||
self.sleepTimeRemaining = secondsUntilSleep
|
self.sleepTimeRemaining = secondsUntilSleep
|
||||||
|
|
||||||
DispatchQueue.runOnMainQueue {
|
DispatchQueue.runOnMainQueue {
|
||||||
self.sleepTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
|
self.sleepTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
|
||||||
if self.isPlaying() {
|
if self?.isPlaying() ?? false {
|
||||||
self.decrementSleepTimerIfRunning()
|
self?.decrementSleepTimerIfRunning()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue