From 31b9e89dba06e709c679ba19d5fa6233b1908c5f Mon Sep 17 00:00:00 2001 From: tanhakabir Date: Sat, 8 May 2021 18:42:20 -0700 Subject: [PATCH] add extra data for queuing and change order of clearing mediaInfo --- Source/SAPlayer.swift | 37 ++++++++++++++++-------------- Source/SAPlayerPresenter.swift | 42 +++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/Source/SAPlayer.swift b/Source/SAPlayer.swift index 92159be..06201d8 100644 --- a/Source/SAPlayer.swift +++ b/Source/SAPlayer.swift @@ -183,7 +183,7 @@ public class SAPlayer { public var audioQueued: [URL] { get { return presenter.audioQueue.map { (queued) -> URL in - return queued.1 + return queued.url } } } @@ -414,14 +414,14 @@ extension SAPlayer { - Parameter mediaInfo: The media information of the audio to show on the lockscreen media player (optional). */ public func startSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo? = nil) { - self.mediaInfo = mediaInfo + + // Because we support queueing, we want to clear off any existing players. + // Therefore, instantiate new player every time, destroy any existing ones. + // This prevents a crash where an owning engine already exists. + presenter.handleClear() + presenter.handlePlaySavedAudio(withSavedUrl: url) - } - - @available(*, deprecated, renamed: "startSavedAudio") - public func initializeSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo? = nil) { self.mediaInfo = mediaInfo - presenter.handlePlaySavedAudio(withSavedUrl: url) } /** @@ -453,14 +453,14 @@ extension SAPlayer { - Parameter mediaInfo: The media information of the audio to show on the lockscreen media player (optional). */ public func startRemoteAudio(withRemoteUrl url: URL, bitrate: SAPlayerBitrate = .high, mediaInfo: SALockScreenInfo? = nil) { - self.mediaInfo = mediaInfo + + // Because we support queueing, we want to clear off any existing players. + // Therefore, instantiate new player every time, destroy any existing ones. + // This prevents a crash where an owning engine already exists. + presenter.handleClear() + presenter.handlePlayStreamedAudio(withRemoteUrl: url, bitrate: bitrate) - } - - @available(*, deprecated, renamed: "startRemoteAudio") - public func initializeRemoteAudio(withRemoteUrl url: URL, mediaInfo: SALockScreenInfo? = nil) { self.mediaInfo = mediaInfo - presenter.handlePlayStreamedAudio(withRemoteUrl: url, bitrate: .high) } /** @@ -474,18 +474,21 @@ extension SAPlayer { Queues remote audio to be played next. The URLs in the queue can be both remote or on disk but once the queued audio starts playing it will start buffering and loading then. This means no guarantee for a 'gapless' playback where there might be several moments in between one audio ending and another starting due to buffering remote audio. - Parameter withRemoteUrl: The URL of the remote audio. + - Parameter bitrate: The bitrate of the streamed audio. By default the bitrate is set to high for streaming saved audio files. If you want to stream radios then you should use the `low` bitrate option. + - Parameter mediaInfo: The media information of the audio to show on the lockscreen media player (optional). */ - public func queueRemoteAudio(withRemoteUrl url: URL) { - presenter.handleQueueStreamedAudio(withRemoteUrl: url) + public func queueRemoteAudio(withRemoteUrl url: URL, bitrate: SAPlayerBitrate = .high, mediaInfo: SALockScreenInfo? = nil) { + presenter.handleQueueStreamedAudio(withRemoteUrl: url, mediaInfo: mediaInfo, bitrate: bitrate) } /** Queues saved audio to be played next. The URLs in the queuecan be both remote or on disk but once the queued audio starts playing it will start buffering and loading then. This means no guarantee for a 'gapless' playback where there might be several moments in between one audio ending and another starting due to buffering remote audio. - Parameter withSavedUrl: The URL of the audio saved on the device. + - Parameter mediaInfo: The media information of the audio to show on the lockscreen media player (optional). */ - public func queueSavedAudio(withSavedUrl url: URL) { - presenter.handleQueueSavedAudio(withSavedUrl: url) + public func queueSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo? = nil) { + presenter.handleQueueSavedAudio(withSavedUrl: url, mediaInfo: mediaInfo) } /** diff --git a/Source/SAPlayerPresenter.swift b/Source/SAPlayerPresenter.swift index 530b17a..a20e83e 100644 --- a/Source/SAPlayerPresenter.swift +++ b/Source/SAPlayerPresenter.swift @@ -28,6 +28,20 @@ import AVFoundation import MediaPlayer class SAPlayerPresenter { + struct QueueItem { + var loc: Location + var url: URL + var mediaInfo: SALockScreenInfo? + var bitrate: SAPlayerBitrate + + init(loc: Location, url: URL, mediaInfo: SALockScreenInfo?, bitrate: SAPlayerBitrate = .high) { + self.loc = loc + self.url = url + self.mediaInfo = mediaInfo + self.bitrate = bitrate + } + } + enum Location { case remote case disk @@ -48,7 +62,7 @@ class SAPlayerPresenter { var durationRef:UInt = 0 var needleRef:UInt = 0 var playingStatusRef:UInt = 0 - var audioQueue: [(Location, URL)] = [] + var audioQueue: [QueueItem] = [] init(delegate: SAPlayerDelegate?) { self.delegate = delegate @@ -79,29 +93,21 @@ class SAPlayerPresenter { } func handlePlaySavedAudio(withSavedUrl url: URL) { - // Because we support queueing, we want to clear off any existing players. - // Therefore, instantiate new player every time, destroy any existing ones. - // This prevents a crash where an owning engine already exists. - handleClear() attachForUpdates(url: url) delegate?.startAudioDownloaded(withSavedUrl: url) } func handlePlayStreamedAudio(withRemoteUrl url: URL, bitrate: SAPlayerBitrate) { - // Because we support queueing, we want to clear off any existing players. - // Therefore, instantiate new player every time, destroy any existing ones. - // This prevents a crash where an owning engine already exists. - handleClear() attachForUpdates(url: url) delegate?.startAudioStreamed(withRemoteUrl: url, bitrate: bitrate) } - func handleQueueStreamedAudio(withRemoteUrl url: URL) { - audioQueue.append((.remote, url)) + func handleQueueStreamedAudio(withRemoteUrl url: URL, mediaInfo: SALockScreenInfo?, bitrate: SAPlayerBitrate) { + audioQueue.append(QueueItem(loc: .remote, url: url, mediaInfo: mediaInfo, bitrate: bitrate)) } - func handleQueueSavedAudio(withSavedUrl url: URL) { - audioQueue.append((.disk, url)) + func handleQueueSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo?) { + audioQueue.append(QueueItem(loc: .disk, url: url, mediaInfo: mediaInfo)) } private func attachForUpdates(url: URL) { @@ -238,11 +244,11 @@ extension SAPlayerPresenter { return } let nextAudioURL = audioQueue.removeFirst() - let key = nextAudioURL.1.key + let key = nextAudioURL.url.key Log.info("getting ready to play \(nextAudioURL)") - AudioQueueDirector.shared.changeInQueue(key, url: nextAudioURL.1) + AudioQueueDirector.shared.changeInQueue(key, url: nextAudioURL.url) handleClear() @@ -250,12 +256,12 @@ extension SAPlayerPresenter { Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { [weak self] (_) in guard let self = self else { return } - switch nextAudioURL.0 { + switch nextAudioURL.loc { case .remote: - self.handlePlayStreamedAudio(withRemoteUrl: nextAudioURL.1, bitrate: .high) // TODO fix to add option for low birate + self.handlePlayStreamedAudio(withRemoteUrl: nextAudioURL.url, bitrate: nextAudioURL.bitrate) break case .disk: - self.handlePlaySavedAudio(withSavedUrl: nextAudioURL.1) + self.handlePlaySavedAudio(withSavedUrl: nextAudioURL.url) } self.shouldPlayImmediately = true