Compare commits

...

5 Commits

Author SHA1 Message Date
David Chavez acab6473b2 Release 0.13.2 2021-08-12 11:40:50 +02:00
David Chavez 57b6fb08f3 Fix tests 2021-08-12 11:40:21 +02:00
David Chavez 68a15ab3a6 Release 0.13.1 2021-08-12 11:18:08 +02:00
David Chavez 92053a2bd0 Add event for queue index changes 2021-08-12 11:16:56 +02:00
David Chavez aeef676164 Persist rate accross player vs item 2021-08-12 11:16:46 +02:00
27 changed files with 81 additions and 44 deletions
+10 -10
View File
@@ -44,9 +44,9 @@
607FACEC1AFB9204008FA782 /* AVPlayerObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* AVPlayerObserverTests.swift */; };
9B05AA312660276400C7A389 /* Quick in Frameworks */ = {isa = PBXBuildFile; productRef = 9B05AA302660276400C7A389 /* Quick */; };
9B05AA332660276400C7A389 /* Nimble in Frameworks */ = {isa = PBXBuildFile; productRef = 9B05AA322660276400C7A389 /* Nimble */; };
9B05AA3A266028E200C7A389 /* SwiftAudio in Frameworks */ = {isa = PBXBuildFile; productRef = 9B05AA39266028E200C7A389 /* SwiftAudio */; };
9B05AA3C26602C0E00C7A389 /* SwiftAudio in Frameworks */ = {isa = PBXBuildFile; productRef = 9B05AA3B26602C0E00C7A389 /* SwiftAudio */; };
9B521D0E2662937600EF0C3A /* MockDispatchQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B521D0D2662937600EF0C3A /* MockDispatchQueue.swift */; };
9B77D79426C522D0004BAF2F /* SwiftAudioEx in Frameworks */ = {isa = PBXBuildFile; productRef = 9B77D79326C522D0004BAF2F /* SwiftAudioEx */; };
9B77D79626C52382004BAF2F /* SwiftAudioEx in Frameworks */ = {isa = PBXBuildFile; productRef = 9B77D79526C52382004BAF2F /* SwiftAudioEx */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -103,7 +103,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9B05AA3A266028E200C7A389 /* SwiftAudio in Frameworks */,
9B77D79426C522D0004BAF2F /* SwiftAudioEx in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -111,7 +111,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9B05AA3C26602C0E00C7A389 /* SwiftAudio in Frameworks */,
9B77D79626C52382004BAF2F /* SwiftAudioEx in Frameworks */,
9B05AA312660276400C7A389 /* Quick in Frameworks */,
9B05AA332660276400C7A389 /* Nimble in Frameworks */,
);
@@ -244,7 +244,7 @@
);
name = SwiftAudio_Example;
packageProductDependencies = (
9B05AA39266028E200C7A389 /* SwiftAudio */,
9B77D79326C522D0004BAF2F /* SwiftAudioEx */,
);
productName = SwiftAudio;
productReference = 607FACD01AFB9204008FA782 /* SwiftAudio_Example.app */;
@@ -267,7 +267,7 @@
packageProductDependencies = (
9B05AA302660276400C7A389 /* Quick */,
9B05AA322660276400C7A389 /* Nimble */,
9B05AA3B26602C0E00C7A389 /* SwiftAudio */,
9B77D79526C52382004BAF2F /* SwiftAudioEx */,
);
productName = Tests;
productReference = 607FACE51AFB9204008FA782 /* SwiftAudio_Tests.xctest */;
@@ -672,13 +672,13 @@
package = 9B05AA2C2660274F00C7A389 /* XCRemoteSwiftPackageReference "Nimble" */;
productName = Nimble;
};
9B05AA39266028E200C7A389 /* SwiftAudio */ = {
9B77D79326C522D0004BAF2F /* SwiftAudioEx */ = {
isa = XCSwiftPackageProductDependency;
productName = SwiftAudio;
productName = SwiftAudioEx;
};
9B05AA3B26602C0E00C7A389 /* SwiftAudio */ = {
9B77D79526C52382004BAF2F /* SwiftAudioEx */ = {
isa = XCSwiftPackageProductDependency;
productName = SwiftAudio;
productName = SwiftAudioEx;
};
/* End XCSwiftPackageProductDependency section */
};
+1 -1
View File
@@ -7,7 +7,7 @@
//
import Foundation
import SwiftAudio
import SwiftAudioEx
class AudioController {
+1 -1
View File
@@ -7,7 +7,7 @@
//
import UIKit
import SwiftAudio
import SwiftAudioEx
class QueueViewController: UIViewController {
+1 -1
View File
@@ -7,7 +7,7 @@
//
import UIKit
import SwiftAudio
import SwiftAudioEx
import AVFoundation
import MediaPlayer
@@ -2,7 +2,7 @@ import Quick
import Nimble
import AVFoundation
@testable import SwiftAudio
@testable import SwiftAudioEx
class AVPlayerItemNotificationObserverTests: QuickSpec {
@@ -2,7 +2,7 @@ import Quick
import Nimble
import AVFoundation
@testable import SwiftAudio
@testable import SwiftAudioEx
class AVPlayerItemObserverTests: QuickSpec {
+1 -1
View File
@@ -2,7 +2,7 @@ import Quick
import Nimble
import AVFoundation
@testable import SwiftAudio
@testable import SwiftAudioEx
class AVPlayerObserverTests: QuickSpec, AVPlayerObserverDelegate {
@@ -2,7 +2,7 @@ import Quick
import Nimble
import AVFoundation
@testable import SwiftAudio
@testable import SwiftAudioEx
class AVPlayerTimeObserverTests: QuickSpec {
+1 -1
View File
@@ -1,7 +1,7 @@
import AVFoundation
import XCTest
@testable import SwiftAudio
@testable import SwiftAudioEx
class AVPlayerWrapperTests: XCTestCase {
+1 -1
View File
@@ -2,7 +2,7 @@ import Quick
import Nimble
import MediaPlayer
@testable import SwiftAudio
@testable import SwiftAudioEx
class AudioPlayerEventTests: QuickSpec {
+3 -3
View File
@@ -3,7 +3,7 @@ import Nimble
import AVFoundation
import XCTest
@testable import SwiftAudio
@testable import SwiftAudioEx
class AudioPlayerTests: XCTestCase {
@@ -124,8 +124,8 @@ class AudioPlayerTests: XCTestCase {
// MARK: - Rate
func test_AudioPlayer__rate__should_be_0() {
XCTAssert(audioPlayer.rate == 0.0)
func test_AudioPlayer__rate__should_be_1() {
XCTAssert(audioPlayer.rate == 1.0)
}
func test_AudioPlayer__rate__playing_source__should_be_1() {
@@ -2,7 +2,7 @@ import Quick
import Nimble
import AVFoundation
@testable import SwiftAudio
@testable import SwiftAudioEx
class AudioSessionControllerTests: QuickSpec {
+1 -1
View File
@@ -9,7 +9,7 @@
import Foundation
import AVFoundation
@testable import SwiftAudio
@testable import SwiftAudioEx
class NonFailingAudioSession: AudioSession {
+1 -1
View File
@@ -8,7 +8,7 @@
import Foundation
@testable import SwiftAudio
@testable import SwiftAudioEx
final class MockDispatchQueue: DispatchQueueType {
func async(flags: DispatchWorkItemFlags, execute work: @escaping @convention(block) () -> Void) {
@@ -9,7 +9,7 @@
import Foundation
import AVFoundation
@testable import SwiftAudio
@testable import SwiftAudioEx
class NowPlayingInfoCenter_Mock: NowPlayingInfoCenter {
@@ -9,7 +9,7 @@
import Foundation
import MediaPlayer
@testable import SwiftAudio
@testable import SwiftAudioEx
class NowPlayingInfoController_Mock: NowPlayingInfoControllerProtocol {
@@ -2,7 +2,7 @@ import Quick
import Nimble
import MediaPlayer
@testable import SwiftAudio
@testable import SwiftAudioEx
class NowPlayingInfoControllerTests: QuickSpec {
+1 -1
View File
@@ -2,7 +2,7 @@ import Quick
import Nimble
import MediaPlayer
@testable import SwiftAudio
@testable import SwiftAudioEx
/// Tests that the AudioPlayer is automatically updating the values it should update in the NowPlayingInfoController.
class NowPlayingInfoTests: QuickSpec {
+1 -1
View File
@@ -1,7 +1,7 @@
import Quick
import Nimble
@testable import SwiftAudio
@testable import SwiftAudioEx
class QueueManagerTests: QuickSpec {
+1 -1
View File
@@ -1,7 +1,7 @@
import Quick
import Nimble
@testable import SwiftAudio
@testable import SwiftAudioEx
class QueuedAudioPlayerTests: QuickSpec {
override func spec() {
+1 -1
View File
@@ -7,7 +7,7 @@
//
import Foundation
import SwiftAudio
import SwiftAudioEx
import UIKit
struct Source {
+5 -5
View File
@@ -6,14 +6,14 @@ let package = Package(
platforms: [.iOS(.v10)],
products: [
.library(
name: "SwiftAudio",
targets: ["SwiftAudio"]),
name: "SwiftAudioEx",
targets: ["SwiftAudioEx"]),
],
dependencies: [],
targets: [
.target(
name: "SwiftAudio",
name: "SwiftAudioEx",
dependencies: [],
path: "SwiftAudio/Classes")
path: "SwiftAudioEx/Classes")
]
)
)
+1 -1
View File
@@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = 'SwiftAudioEx'
s.version = '0.13.0'
s.version = '0.13.2'
s.summary = 'Easy audio streaming for iOS'
s.description = <<-DESC
SwiftAudioEx is an audio player written in Swift, making it simpler to work with audio playback from streams and files.
+15 -3
View File
@@ -115,9 +115,17 @@ public class AudioPlayer: AVPlayerWrapperDelegate {
set { _wrapper.isMuted = newValue }
}
private var _rate: Float = 1.0
public var rate: Float {
get { return wrapper.rate }
set { _wrapper.rate = newValue }
get { return _rate }
set {
_rate = newValue
// Only set the rate on the wrapper if it is already playing.
if _wrapper.rate > 0 {
_wrapper.rate = newValue
}
}
}
// MARK: - Init
@@ -311,7 +319,11 @@ public class AudioPlayer: AVPlayerWrapperDelegate {
updateNowPlayingPlaybackValues()
}
setTimePitchingAlgorithmForCurrentItem()
case .playing, .paused:
case .playing:
// When a track starts playing, reset the rate to the stored rate
self.rate = _rate;
fallthrough
case .paused:
if (automaticallyUpdateNowPlayingInfo) {
updateNowPlayingPlaybackValues()
}
+8 -1
View File
@@ -18,6 +18,7 @@ extension AudioPlayer {
public typealias UpdateDurationEventData = (Double)
public typealias MetadataEventData = ([AVMetadataItem])
public typealias DidRecreateAVPlayerEventData = ()
public typealias QueueIndexEventData = (previousIndex: Int?, newIndex: Int?)
public struct EventHolder {
@@ -70,7 +71,13 @@ extension AudioPlayer {
- Note: It can be necessary to set the AVAudioSession's category again when this event is emitted.
*/
public let didRecreateAVPlayer: AudioPlayer.Event<()> = AudioPlayer.Event()
/**
Emitted when a new track starts and the queue index changes.
- Important: Remember to dispatch to the main queue if any UI is updated in the event handler.
- Note: It is only fired for instances of a QueuedAudioPlayer.
*/
public let queueIndex: AudioPlayer.Event<QueueIndexEventData> = AudioPlayer.Event()
}
public typealias EventClosure<EventData> = (EventData) -> Void
+1 -1
View File
@@ -7,7 +7,7 @@
import Foundation
protocol QueueManagerDelegate: class {
protocol QueueManagerDelegate: AnyObject {
func onReceivedFirstItem()
func onCurrentIndexChanged(oldIndex: Int, newIndex: Int)
}
+19 -1
View File
@@ -11,10 +11,15 @@ import MediaPlayer
/**
An audio player that can keep track of a queue of AudioItems.
*/
public class QueuedAudioPlayer: AudioPlayer {
public class QueuedAudioPlayer: AudioPlayer, QueueManagerDelegate {
let queueManager: QueueManager = QueueManager<AudioItem>()
public override init(nowPlayingInfoController: NowPlayingInfoControllerProtocol = NowPlayingInfoController(), remoteCommandController: RemoteCommandController = RemoteCommandController()) {
super.init(nowPlayingInfoController: nowPlayingInfoController, remoteCommandController: remoteCommandController)
queueManager.delegate = self
}
/// The repeat mode for the queue player.
public var repeatMode: RepeatMode = .off
@@ -34,6 +39,7 @@ public class QueuedAudioPlayer: AudioPlayer {
*/
public override func stop() {
super.stop()
self.event.queueIndex.emit(data: (currentIndex, nil))
}
override func reset() {
@@ -199,4 +205,16 @@ public class QueuedAudioPlayer: AudioPlayer {
} catch { /* TODO: handle possible errors from load */ }
}
}
// MARK: - QueueManagerDelegate
func onCurrentIndexChanged(oldIndex: Int, newIndex: Int) {
// if _currentItem is nil, then this was triggered by a reset. ignore.
if _currentItem == nil { return }
self.event.queueIndex.emit(data: (oldIndex, newIndex))
}
func onReceivedFirstItem() {
self.event.queueIndex.emit(data: (nil, 0))
}
}