Compare commits

..

8 Commits

Author SHA1 Message Date
Tanha 3e66b4b4d4 Release 2.8.1 2020-01-04 13:35:29 -08:00
Tanha 58bbc97a1b Minor fix on end of audio notification 2020-01-04 13:35:03 -08:00
Tanha 8d9e9d92f4 Release 2.8.0 2020-01-04 13:24:47 -08:00
tanhakabir 03392c21e0 fix bug in notification of end of audio in PlayingStatus (#25) 2020-01-04 13:23:50 -08:00
Tanha 924170d159 Release 2.7.0 2020-01-04 02:04:35 -08:00
tanhakabir b355eb4e09 add api for buffer progress in SAAvailabilityRange (#24) 2020-01-04 02:02:56 -08:00
Tanha 1373a816a6 Release 2.6.0 2019-12-18 21:23:07 -08:00
tanhakabir 196b04a703 Rename and deprecate initialize functions (#23) 2019-12-18 21:22:28 -08:00
8 changed files with 50 additions and 25 deletions
@@ -145,11 +145,9 @@ class ViewController: UIViewController {
if self.duration == 0.0 { return }
let progress = Float((buffer.totalDurationBuffered + buffer.startingBufferTimePositon) / self.duration)
self.bufferProgress.progress = Float(buffer.bufferingProgress)
self.bufferProgress.progress = progress
if progress >= 0.99 {
if buffer.bufferingProgress >= 0.99 {
self.streamButton.isEnabled = false
}
@@ -244,7 +242,7 @@ class ViewController: UIViewController {
self.currentUrlLocationLabel.text = "saved to: \(url.lastPathComponent)"
self.savedUrls[self.selectedAudio] = url
SAPlayer.shared.initializeSavedAudio(withSavedUrl: url)
SAPlayer.shared.startSavedAudio(withSavedUrl: url)
}
})
streamButton.isEnabled = false
@@ -259,7 +257,7 @@ class ViewController: UIViewController {
@IBAction func streamTouched(_ sender: Any) {
if !isStreaming {
SAPlayer.shared.initializeRemoteAudio(withRemoteUrl: selectedAudio.url)
SAPlayer.shared.startRemoteAudio(withRemoteUrl: selectedAudio.url)
streamButton.setTitle("Cancel streaming", for: .normal)
downloadButton.isEnabled = false
} else {
+3 -3
View File
@@ -39,7 +39,7 @@ pod 'SwiftAudioPlayer'
To play remote audio:
```swift
let url = URL(string: "https://randomwebsite.com/audio.mp3")!
SAPlayer.shared.initializeAudio(withRemoteUrl: url)
SAPlayer.shared.startRemoteAudio(withRemoteUrl: url)
SAPlayer.shared.play()
```
@@ -121,8 +121,8 @@ Access the player and all of its fields and functions through `SAPlayer.shared`.
### Playing Audio (Basic Commands)
To set up player with audio to play, use either:
* `initializeSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo?)` to play audio that is saved on the device.
* `initializeRemoteAudio(withRemoteUrl url: URL, mediaInfo: SALockScreenInfo?)` to play audio streamed from a remote location.
* `startSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo?)` to play audio that is saved on the device.
* `startRemoteAudio(withRemoteUrl url: URL, mediaInfo: SALockScreenInfo?)` to play audio streamed from a remote location.
Both of these expect a URL of the location of the audio and an optional media information to display on the lockscreen.
+1 -1
View File
@@ -64,7 +64,7 @@ class AudioDiskEngine: AudioEngine {
audioSampleRate = Float(audioFormat?.sampleRate ?? 44100)
audioLengthSeconds = Float(audioLengthSamples) / audioSampleRate
duration = Duration(audioLengthSeconds)
bufferedSeconds = SAAudioAvailabilityRange(startingNeedle: 0, durationLoadedByNetwork: duration, isPlayable: true)
bufferedSeconds = SAAudioAvailabilityRange(startingNeedle: 0, durationLoadedByNetwork: duration, predictedDurationToLoad: duration, isPlayable: true)
} else {
Log.monitor("Could not load downloaded file with url: \(url)")
}
+7 -3
View File
@@ -86,8 +86,8 @@ class AudioEngine: AudioEngineProtocol {
}
}
var bufferedSecondsDebouncer: SAAudioAvailabilityRange = SAAudioAvailabilityRange(startingNeedle: 0.0, durationLoadedByNetwork: 0.0, isPlayable: false)
var bufferedSeconds: SAAudioAvailabilityRange = SAAudioAvailabilityRange(startingNeedle: 0.0, durationLoadedByNetwork: 0.0, isPlayable: false) {
var bufferedSecondsDebouncer: SAAudioAvailabilityRange = SAAudioAvailabilityRange(startingNeedle: 0.0, durationLoadedByNetwork: 0.0, predictedDurationToLoad: Double.greatestFiniteMagnitude, isPlayable: false)
var bufferedSeconds: SAAudioAvailabilityRange = SAAudioAvailabilityRange(startingNeedle: 0.0, durationLoadedByNetwork: 0.0, predictedDurationToLoad: Double.greatestFiniteMagnitude, isPlayable: false) {
didSet {
if bufferedSeconds.startingNeedle == 0.0 && bufferedSeconds.durationLoadedByNetwork == 0.0 {
bufferedSecondsDebouncer = bufferedSeconds
@@ -154,7 +154,11 @@ class AudioEngine: AudioEngineProtocol {
func updateIsPlaying() {
if !bufferedSeconds.isPlayable {
playingStatus = .buffering
if bufferedSeconds.bufferingProgress > 0.999 {
playingStatus = .ended
} else {
playingStatus = .buffering
}
return
}
+1 -7
View File
@@ -218,7 +218,7 @@ class AudioStreamEngine: AudioEngine {
let range = converter.pollNetworkAudioAvailabilityRange()
isPlayable = (numberOfBuffersScheduledInTotal >= MIN_BUFFERS_TO_BE_PLAYABLE && range.1 > 0) && predictedStreamDuration > 0
Log.debug("loaded \(range), numberOfBuffersScheduledInTotal: \(numberOfBuffersScheduledInTotal), isPlayable: \(isPlayable)")
bufferedSeconds = SAAudioAvailabilityRange(startingNeedle: range.0, durationLoadedByNetwork: range.1, isPlayable: isPlayable)
bufferedSeconds = SAAudioAvailabilityRange(startingNeedle: range.0, durationLoadedByNetwork: range.1, predictedDurationToLoad: predictedStreamDuration, isPlayable: isPlayable)
}
private func updateNeedle() {
@@ -236,12 +236,6 @@ class AudioStreamEngine: AudioEngine {
var currentTime = TimeInterval(playerTime.sampleTime) / playerTime.sampleRate
currentTime = currentTime > 0 ? currentTime : 0
if currentTime > predictedStreamDuration {
Log.info("reached end of audio")
seek(toNeedle: 0)
pause()
playingStatus = .ended
}
needle = (currentTime + currentTimeOffset)
}
@@ -29,8 +29,15 @@ import Foundation
public struct SAAudioAvailabilityRange {
let startingNeedle: Needle
let durationLoadedByNetwork: Duration
let predictedDurationToLoad: Duration
let isPlayable: Bool
public var bufferingProgress: Double {
get {
return (startingNeedle + durationLoadedByNetwork) / predictedDurationToLoad
}
}
public var startingBufferTimePositon: Double {
get {
return startingNeedle
@@ -52,4 +59,8 @@ public struct SAAudioAvailabilityRange {
public func contains(_ needle: Double) -> Bool {
return needle >= startingNeedle && (needle - startingNeedle) < durationLoadedByNetwork
}
public func isCompletelyBuffered() -> Bool {
return startingNeedle + durationLoadedByNetwork >= predictedDurationToLoad
}
}
+22 -4
View File
@@ -198,21 +198,27 @@ public class SAPlayer {
//MARK: - External Player Controls
extension SAPlayer {
/**
Toggles between the play and pause state of the player if the player is not buffering (thus is playable).
Toggles between the play and pause state of the player. If nothing is playable (aka still in buffering state or no audio is initialized) no action will be taken. Please call `startSavedAudio` or `startRemoteAudio` to set up the player with audio before this.
- Note: If you are streaming, wait till the status from `SAPlayer.Updates.PlayingStatus` is not `.buffering`.
*/
public func togglePlayAndPause() {
presenter.handleTogglePlayingAndPausing()
}
/**
Attempts to play the player even if nothing playable is loaded (aka still in buffering state or no audio is initialized).
Attempts to play the player. If nothing is playable (aka still in buffering state or no audio is initialized) no action will be taken. Please call `startSavedAudio` or `startRemoteAudio` to set up the player with audio before this.
- Note: If you are streaming, wait till the status from `SAPlayer.Updates.PlayingStatus` is not `.buffering`.
*/
public func play() {
presenter.handlePlay()
}
/**
Attempts to pause the player even if nothing playable is loaded (aka still in buffering state or no audio is initialized).
Attempts to pause the player. If nothing is playable (aka still in buffering state or no audio is initialized) no action will be taken. Please call `startSavedAudio` or `startRemoteAudio` to set up the player with audio before this.
- Note:If you are streaming, wait till the status from `SAPlayer.Updates.PlayingStatus` is not `.buffering`.
*/
public func pause() {
presenter.handlePause()
@@ -264,13 +270,19 @@ extension SAPlayer {
- 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 startSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo? = nil) {
self.mediaInfo = mediaInfo
presenter.handlePlaySavedAudio(withSavedUrl: url)
}
@available(*, deprecated, renamed: "startSavedAudio")
public func initializeSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo? = nil) {
self.mediaInfo = mediaInfo
presenter.handlePlaySavedAudio(withSavedUrl: url)
}
/**
Sets up player to play audio that will be streamed from a remote location.
Sets up player to play audio that will be streamed from a remote location. After this is called, it will connect to the server and start to receive and process data. The player is not playable the SAAudioAvailabilityRange notifies that player is ready for playing (you can subscribe to these updates through `SAPlayer.Updates.StreamingBuffer`). You can alternatively see when the player is available to play by subscribing to `SAPlayer.Updates.PlayingStatus` and waiting for a status that isn't `.buffering`.
- Important: If intending to use [AVAudioUnit](https://developer.apple.com/documentation/avfoundation/audio_track_engineering/audio_engine_building_blocks/audio_enhancements) audio modifiers during playback, the list of audio modifiers under `SAPlayer.shared.audioModifiers` must be finalized before calling this function. After all realtime audio manipulations within the this will be effective.
@@ -279,6 +291,12 @@ extension SAPlayer {
- Parameter withRemoteUrl: The URL of the remote audio.
- Parameter mediaInfo: The media information of the audio to show on the lockscreen media player (optional).
*/
public func startRemoteAudio(withRemoteUrl url: URL, mediaInfo: SALockScreenInfo? = nil) {
self.mediaInfo = mediaInfo
presenter.handlePlayStreamedAudio(withRemoteUrl: url)
}
@available(*, deprecated, renamed: "startRemoteAudio")
public func initializeRemoteAudio(withRemoteUrl url: URL, mediaInfo: SALockScreenInfo? = nil) {
self.mediaInfo = mediaInfo
presenter.handlePlayStreamedAudio(withRemoteUrl: url)
+1 -1
View File
@@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = 'SwiftAudioPlayer'
s.version = '2.5.2'
s.version = '2.8.1'
s.summary = 'SwiftAudioPlayer is a Swift based audio player that can handle streaming from a remote location and audio manipulation.'
# This description is used to generate tags and improve search results.