diff --git a/Source/Engine/AudioStreamEngine.swift b/Source/Engine/AudioStreamEngine.swift index b3fb310..9d5d426 100644 --- a/Source/Engine/AudioStreamEngine.swift +++ b/Source/Engine/AudioStreamEngine.swift @@ -242,7 +242,14 @@ 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, predictedDurationToLoad: predictedStreamDuration, isPlayable: isPlayable) + + if AudioDataManager.shared.currentStreamFinished { + AudioDataManager.shared.updateDuration(d: range.1); + bufferedSeconds = SAAudioAvailabilityRange(startingNeedle: range.0, durationLoadedByNetwork: range.1, predictedDurationToLoad: range.1, isPlayable: isPlayable) + }else { + bufferedSeconds = SAAudioAvailabilityRange(startingNeedle: range.0, durationLoadedByNetwork: range.1, predictedDurationToLoad: predictedStreamDuration, isPlayable: isPlayable) + } + } private func updateNeedle() { @@ -265,7 +272,11 @@ class AudioStreamEngine: AudioEngine { private func updateDuration() { if let d = converter.pollPredictedDuration() { - self.predictedStreamDuration = d + if AudioDataManager.shared.currentStreamFinished { + self.predictedStreamDuration = AudioDataManager.shared.currentStreamFinishedWithDuration + }else { + self.predictedStreamDuration = d + } } } diff --git a/Source/Model/AudioDataManager.swift b/Source/Model/AudioDataManager.swift index 9d2560c..a4b132b 100644 --- a/Source/Model/AudioDataManager.swift +++ b/Source/Model/AudioDataManager.swift @@ -26,6 +26,8 @@ import Foundation protocol AudioDataManagable { + var currentStreamFinished: Bool { get } + var currentStreamFinishedWithDuration: Duration { get } var numberOfQueued: Int { get } var numberOfActive: Int { get } @@ -38,6 +40,7 @@ protocol AudioDataManagable { func setDownloadDirectory(_ dir: FileManager.SearchPathDirectory) func clear() + func updateDuration(d: Duration) //Director pattern func attach(callback: @escaping (_ id: ID, _ progress: Double)->()) @@ -55,9 +58,14 @@ protocol AudioDataManagable { } class AudioDataManager: AudioDataManagable { + var currentStreamFinishedWithDuration: Duration = 0 + var allowCellular: Bool = true var downloadDirectory: FileManager.SearchPathDirectory = .documentDirectory + public var currentStreamFinished = false + public var totalStreamedDuration = 0 + static let shared: AudioDataManagable = AudioDataManager() // When we're streaming we want to stagger the size of data push up from disk to prevent the phone from freezing. We push up data of this chunk size every couple milliseconds. @@ -96,6 +104,10 @@ class AudioDataManager: AudioDataManagable { doneCallback: streamDoneListener) } + func updateDuration(d: Duration) { + currentStreamFinishedWithDuration = d + } + func clear() { streamingCallbacks = [] } @@ -125,6 +137,7 @@ class AudioDataManager: AudioDataManagable { // MARK:- Streaming extension AudioDataManager { func startStream(withRemoteURL url: AudioURL, callback: @escaping (StreamProgressPTO) -> ()) { + currentStreamFinished = false if let data = FileStorage.Audio.read(url.key) { let dto = StreamProgressDTO.init(progress: 1.0, data: data, totalBytesExpected: Int64(data.count)) callback(StreamProgressPTO(dto: dto)) @@ -154,10 +167,12 @@ extension AudioDataManager { streamWorker.resume(withId: url.key) } func seekStream(withRemoteURL url: AudioURL, toByteOffset offset: UInt64) { + currentStreamFinished = false streamWorker.seek(withId: url.key, withByteOffset: offset) } func deleteStream(withRemoteURL url: AudioURL) { + currentStreamFinished = false streamWorker.stop(withId: url.key) streamingCallbacks.removeAll { (cb: (ID, (StreamProgressPTO) -> ())) -> Bool in return cb.0 == url.key @@ -226,11 +241,12 @@ extension AudioDataManager { globalDownloadProgressCallback(id, 1.0) } + private func streamDoneListener(id: ID, error: Error?) -> Bool { if error != nil { return false } - + currentStreamFinished = true downloadWorker.resumeAllActive() return false }