Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ddf26e206e | |||
| e319134eb8 | |||
| 9599f66a0f | |||
| ef231a2570 | |||
| 350e6ec064 | |||
| ad63b89ede | |||
| 43e887b823 | |||
| 006b94ea10 | |||
| abb0a29fb4 | |||
| ed3ba9698d | |||
| 294902e3fe | |||
| 764f0b130b | |||
| c25071d83a | |||
| 19db1fc74b |
@@ -0,0 +1,6 @@
|
||||
# Changelog
|
||||
|
||||
## 7.3.0
|
||||
|
||||
- Take in PR from @cntrump to use the non-deprecated subscription pattern in loop feature
|
||||
|
||||
+2
@@ -135,6 +135,7 @@
|
||||
A470FE1B25F9AEB900F135FF /* AudioQueueDirector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioQueueDirector.swift; sourceTree = "<group>"; };
|
||||
A470FE2025F9AF1400F135FF /* AudioQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioQueue.swift; sourceTree = "<group>"; };
|
||||
A4827770262A216C00B6918A /* StreamingDownloadDirector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamingDownloadDirector.swift; sourceTree = "<group>"; };
|
||||
A4883AC926CC25DE0073B8B6 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
|
||||
A4B4CC112223ED2A0045554B /* SAPlayerDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SAPlayerDownloader.swift; sourceTree = "<group>"; };
|
||||
A4FBA6B3221B74C900D5A353 /* SAPlayerHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SAPlayerHelpers.swift; sourceTree = "<group>"; };
|
||||
A4FBA6B6221BAC3D00D5A353 /* SAPlayerUpdateSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SAPlayerUpdateSubscription.swift; sourceTree = "<group>"; };
|
||||
@@ -255,6 +256,7 @@
|
||||
children = (
|
||||
15DF3E7F1B5E10B1BBE49D3E9A67C938 /* LICENSE */,
|
||||
B8C829A46249957CD3056074B5CC0BBB /* README.md */,
|
||||
A4883AC926CC25DE0073B8B6 /* CHANGELOG.md */,
|
||||
6EC04ECC8F7CB2AF2E4E042A6A8ECFA1 /* SwiftAudioPlayer.podspec */,
|
||||
A4523BC8220A0B3C0079C4BC /* Credited_LICENSE */,
|
||||
);
|
||||
|
||||
@@ -115,10 +115,11 @@ class AudioDiskEngine: AudioEngine {
|
||||
}
|
||||
|
||||
let playing = playerNode.isPlaying
|
||||
let seekToNeedle = needle > Needle(duration) ? Needle(duration) : needle
|
||||
|
||||
self.needle = needle // to tick while paused
|
||||
self.needle = seekToNeedle // to tick while paused
|
||||
|
||||
seekFrame = AVAudioFramePosition(Float(needle) * audioSampleRate)
|
||||
seekFrame = AVAudioFramePosition(Float(seekToNeedle) * audioSampleRate)
|
||||
seekFrame = max(seekFrame, 0)
|
||||
seekFrame = min(seekFrame, audioLengthSamples)
|
||||
currentPosition = seekFrame
|
||||
|
||||
@@ -273,6 +273,15 @@ class AudioStreamEngine: AudioEngine {
|
||||
//MARK:- Overriden From Parent
|
||||
override func seek(toNeedle needle: Needle) {
|
||||
Log.info("didSeek to needle: \(needle)")
|
||||
|
||||
// if not playable (data not loaded etc), duration could be zero.
|
||||
guard isPlayable else {
|
||||
if predictedStreamDuration == 0 {
|
||||
seekNeedleCommandBeforeEngineWasReady = needle
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
guard needle < (ceil(predictedStreamDuration)) else {
|
||||
if !isPlayable {
|
||||
seekNeedleCommandBeforeEngineWasReady = needle
|
||||
|
||||
@@ -30,10 +30,12 @@ protocol AudioDataManagable {
|
||||
var numberOfActive: Int { get }
|
||||
|
||||
var allowCellular: Bool { get set }
|
||||
var downloadDirectory: FileManager.SearchPathDirectory { get }
|
||||
|
||||
func setHTTPHeaderFields(_ fields: [String: String]?)
|
||||
func setBackgroundCompletionHandler(_ completionHandler: @escaping () -> ())
|
||||
func setAllowCellularDownloadPreference(_ preference: Bool)
|
||||
func setDownloadDirectory(_ dir: FileManager.SearchPathDirectory)
|
||||
|
||||
func clear()
|
||||
|
||||
@@ -54,6 +56,7 @@ protocol AudioDataManagable {
|
||||
|
||||
class AudioDataManager: AudioDataManagable {
|
||||
var allowCellular: Bool = true
|
||||
var downloadDirectory: FileManager.SearchPathDirectory = .documentDirectory
|
||||
|
||||
static let shared: AudioDataManagable = AudioDataManager()
|
||||
|
||||
@@ -110,6 +113,10 @@ class AudioDataManager: AudioDataManagable {
|
||||
allowCellular = preference
|
||||
}
|
||||
|
||||
func setDownloadDirectory(_ dir: FileManager.SearchPathDirectory) {
|
||||
downloadDirectory = dir
|
||||
}
|
||||
|
||||
func attach(callback: @escaping (_ id: ID, _ progress: Double)->()) {
|
||||
globalDownloadProgressCallback = callback
|
||||
}
|
||||
|
||||
@@ -64,9 +64,14 @@ struct FileStorage {
|
||||
// MARK:- Audio
|
||||
extension FileStorage {
|
||||
struct Audio {
|
||||
private static let directory: FileManager.SearchPathDirectory = .documentDirectory
|
||||
private init() {}
|
||||
|
||||
private static var directory: FileManager.SearchPathDirectory {
|
||||
get {
|
||||
return AudioDataManager.shared.downloadDirectory
|
||||
}
|
||||
}
|
||||
|
||||
static func isStored(_ id: ID) -> Bool {
|
||||
guard let url = locate(id)?.path else {
|
||||
return false
|
||||
@@ -103,7 +108,7 @@ extension FileStorage {
|
||||
}
|
||||
|
||||
static func locate(_ id: ID) -> URL? {
|
||||
let folderUrls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
||||
let folderUrls = FileManager.default.urls(for: directory, in: .userDomainMask)
|
||||
guard folderUrls.count != 0 else { return nil }
|
||||
|
||||
if let urls = try? FileManager.default.contentsOfDirectory(at: folderUrls[0], includingPropertiesForKeys: nil) {
|
||||
|
||||
@@ -585,8 +585,7 @@ extension SAPlayer: SAPlayerDelegate {
|
||||
}
|
||||
|
||||
internal func seekEngine(toNeedle needle: Needle) {
|
||||
var seekToNeedle = needle < 0 ? 0 : needle
|
||||
seekToNeedle = needle > Needle(duration ?? 0) ? Needle(duration ?? 0) : needle
|
||||
let seekToNeedle = needle < 0 ? 0 : needle
|
||||
player?.seek(toNeedle: seekToNeedle)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,5 +109,14 @@ extension SAPlayer {
|
||||
AudioDataManager.shared.setAllowCellularDownloadPreference(allowUsingCellularData)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
EXPERIMENTAL!
|
||||
*/
|
||||
public static var downloadDirectory: FileManager.SearchPathDirectory = .documentDirectory {
|
||||
didSet {
|
||||
AudioDataManager.shared.setDownloadDirectory(downloadDirectory)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ extension SAPlayer {
|
||||
|
||||
guard playingStatusId == nil else { return }
|
||||
|
||||
playingStatusId = SAPlayer.Updates.PlayingStatus.subscribe({ (url, status) in
|
||||
playingStatusId = SAPlayer.Updates.PlayingStatus.subscribe({ (status) in
|
||||
if status == .ended && enabled {
|
||||
SAPlayer.shared.seekTo(seconds: 0.0)
|
||||
SAPlayer.shared.play()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'SwiftAudioPlayer'
|
||||
s.version = '6.4.0'
|
||||
s.version = '7.3.0'
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user