Skip to content

Commit

Permalink
Improve handling of playWhenReady parameters (#69)
Browse files Browse the repository at this point in the history
This fixes an issue where calling one of the player methods with an optional playWhenReady parameter with playWhenReady= true, it would first start loading the current track before the track-changing action was called and then it would be called again because the track changed.

Instead, when playWhenReady is false, playback is paused before changing the track. When playWhenReady is true, playback is started after changing the track – which causes only the new track to start loading.
  • Loading branch information
puckey authored Mar 25, 2024
1 parent 03c988e commit ea82b81
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 41 deletions.
73 changes: 49 additions & 24 deletions Sources/SwiftAudioEx/AudioPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,33 @@ public class AudioPlayer: AVPlayerWrapperDelegate {
}
}

/**
Handles the `playWhenReady` setting while executing a given action.

This method takes an optional `Bool` value and a closure representing an action to execute.
If the `Bool` value is not `nil`, `self.playWhenReady` is set accordingly either before or
after executing the action.

- Parameters:
- playWhenReady: Optional `Bool` to set `self.playWhenReady`.
- If `true`, `self.playWhenReady` will be set after executing the action.
- If `false`, `self.playWhenReady` will be set before executing the action.
- If `nil`, `self.playWhenReady` will not be changed.
- action: A closure representing the action to execute. This closure can throw an error.

- Throws: This function will propagate any errors thrown by the `action` closure.
*/
internal func handlePlayWhenReady(_ playWhenReady: Bool?, action: () throws -> Void) rethrows {
if playWhenReady == false {
self.playWhenReady = false
}

try action()

if playWhenReady == true {
self.playWhenReady = true
}
}

// MARK: - Getters from AVPlayerWrapper

Expand Down Expand Up @@ -170,32 +197,30 @@ public class AudioPlayer: AVPlayerWrapperDelegate {
- parameter playWhenReady: Optional, whether to start playback when the item is ready.
*/
public func load(item: AudioItem, playWhenReady: Bool? = nil) {
currentItem = item
handlePlayWhenReady(playWhenReady) {
currentItem = item

if let playWhenReady = playWhenReady {
self.playWhenReady = playWhenReady
}

if (automaticallyUpdateNowPlayingInfo) {
// Reset playback values without updating, because that will happen in
// the loadNowPlayingMetaValues call straight after:
nowPlayingInfoController.setWithoutUpdate(keyValues: [
MediaItemProperty.duration(nil),
NowPlayingInfoProperty.playbackRate(nil),
NowPlayingInfoProperty.elapsedPlaybackTime(nil)
])
loadNowPlayingMetaValues()
if (automaticallyUpdateNowPlayingInfo) {
// Reset playback values without updating, because that will happen in
// the loadNowPlayingMetaValues call straight after:
nowPlayingInfoController.setWithoutUpdate(keyValues: [
MediaItemProperty.duration(nil),
NowPlayingInfoProperty.playbackRate(nil),
NowPlayingInfoProperty.elapsedPlaybackTime(nil)
])
loadNowPlayingMetaValues()
}

enableRemoteCommands(forItem: item)

wrapper.load(
from: item.getSourceUrl(),
type: item.getSourceType(),
playWhenReady: self.playWhenReady,
initialTime: (item as? InitialTiming)?.getInitialTime(),
options:(item as? AssetOptionsProviding)?.getAssetOptions()
)
}

enableRemoteCommands(forItem: item)

wrapper.load(
from: item.getSourceUrl(),
type: item.getSourceType(),
playWhenReady: self.playWhenReady,
initialTime: (item as? InitialTiming)?.getInitialTime(),
options:(item as? AssetOptionsProviding)?.getAssetOptions()
)
}

/**
Expand Down
30 changes: 13 additions & 17 deletions Sources/SwiftAudioEx/QueuedAudioPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ public class QueuedAudioPlayer: AudioPlayer, QueueManagerDelegate {
- parameter playWhenReady: Optional, whether to start playback when the item is ready.
*/
public override func load(item: AudioItem, playWhenReady: Bool? = nil) {
if let playWhenReady = playWhenReady {
self.playWhenReady = playWhenReady
handlePlayWhenReady(playWhenReady) {
queue.replaceCurrentItem(with: item)
}
queue.replaceCurrentItem(with: item)
}

/**
Expand All @@ -81,10 +80,9 @@ public class QueuedAudioPlayer: AudioPlayer, QueueManagerDelegate {
- parameter playWhenReady: Optional, whether to start playback when the item is ready.
*/
public func add(item: AudioItem, playWhenReady: Bool? = nil) {
if let playWhenReady = playWhenReady {
self.playWhenReady = playWhenReady
handlePlayWhenReady(playWhenReady) {
queue.add(item)
}
queue.add(item)
}

/**
Expand All @@ -94,10 +92,9 @@ public class QueuedAudioPlayer: AudioPlayer, QueueManagerDelegate {
- parameter playWhenReady: Optional, whether to start playback when the item is ready.
*/
public func add(items: [AudioItem], playWhenReady: Bool? = nil) {
if let playWhenReady = playWhenReady {
self.playWhenReady = playWhenReady
handlePlayWhenReady(playWhenReady) {
queue.add(items)
}
queue.add(items)
}

public func add(items: [AudioItem], at index: Int) throws {
Expand Down Expand Up @@ -147,15 +144,14 @@ public class QueuedAudioPlayer: AudioPlayer, QueueManagerDelegate {
- throws: `AudioPlayerError`
*/
public func jumpToItem(atIndex index: Int, playWhenReady: Bool? = nil) throws {
if let playWhenReady = playWhenReady {
self.playWhenReady = playWhenReady
try handlePlayWhenReady(playWhenReady) {
if (index == currentIndex) {
seek(to: 0)
} else {
_ = try queue.jump(to: index)
}
event.playbackEnd.emit(data: .jumpedToIndex)
}
if (index == currentIndex) {
seek(to: 0)
} else {
_ = try queue.jump(to: index)
}
event.playbackEnd.emit(data: .jumpedToIndex)
}

/**
Expand Down

0 comments on commit ea82b81

Please sign in to comment.