Reputation: 1472
I am trying to get a very basic audio player set up in a macOS application. I am using Xcode 9.3 on macOS 10.13.4.
I have a MediaManager
class to control the AVPlayer
object:
let EPISODE_SELECTED_KEY = "EPISODE_SELECTED"
class MediaManager {
static var shared: MediaManager = MediaManager()
var player: AVPlayer?
var currentFile: URL? {
didSet {
if (currentFile != nil) {
play(URL: currentFile!)
NotificationCenter.default.post(name: NSNotification.Name(EPISODE_SELECTED_KEY), object: nil)
}
}
}
func play(URL: URL) {
let item = AVPlayerItem(url: URL)
player = AVPlayer(playerItem: item)
player?.play()
}
}
To visually track the progress of the audio item being played, I am subclassing NSSlider
as so:
class PlayerSlider: NSSlider {
var observerToken: Any?
var mediaManager = MediaManager.shared
override var isEnabled: Bool {
didSet {
// Register for PlayerManager notification.
NotificationCenter.default.addObserver(self, selector: #selector(setupPlayerObserver), name: Notification.Name(EPISODE_SELECTED_KEY), object: nil)
}
}
override var doubleValue: Double {
didSet {
// Make sure the player has an active item.
guard mediaManager.currentEpisode != nil || mediaManager.currentFile != nil else {
return
}
// Update player with slider's position.
let seekTime = CMTime(seconds: (mediaManager.player?.currentTime().seconds)! * (doubleValue / 100), preferredTimescale: CMTimeScale(NSEC_PER_SEC))
mediaManager.player?.seek(to: seekTime)
}
}
@objc func setupPlayerObserver() {
// Setup observer to update UI every 0.5 seconds.
let interval = CMTime(seconds: 0.5, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
self.observerToken = mediaManager.player!.addPeriodicTimeObserver(forInterval: interval, queue: .main, using: { (time) in
// Update slider value to audio item progress.
let duration = self.mediaManager.player!.currentItem!.duration.seconds
let seekTime = self.mediaManager.player!.currentTime().seconds
self.doubleValue = seekTime / duration * 100
})
}
}
For testing purposes, I'm just set the currentFile
property of the MediaManager
singleton to a local file.
In the block that I pass to the addPeriodicTimeObserver
function, if I comment out everything the file plays fine. However, if there's even a print statement in there, nothing happens. The file never plays and the app just hangs.
AVPlayer
from playing.MediaManager
singleton and the listener inside the PlayerSlider
.Upvotes: 2
Views: 4265