Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| acab6473b2 | |||
| 57b6fb08f3 | |||
| 68a15ab3a6 | |||
| 92053a2bd0 | |||
| aeef676164 |
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftAudio
|
||||
import SwiftAudioEx
|
||||
|
||||
|
||||
class AudioController {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftAudio
|
||||
import SwiftAudioEx
|
||||
|
||||
|
||||
class QueueViewController: UIViewController {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
import AVFoundation
|
||||
import XCTest
|
||||
|
||||
@testable import SwiftAudio
|
||||
@testable import SwiftAudioEx
|
||||
|
||||
|
||||
class AVPlayerWrapperTests: XCTestCase {
|
||||
|
||||
@@ -2,7 +2,7 @@ import Quick
|
||||
import Nimble
|
||||
import MediaPlayer
|
||||
|
||||
@testable import SwiftAudio
|
||||
@testable import SwiftAudioEx
|
||||
|
||||
class AudioPlayerEventTests: QuickSpec {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
import AVFoundation
|
||||
|
||||
@testable import SwiftAudio
|
||||
@testable import SwiftAudioEx
|
||||
|
||||
|
||||
class NonFailingAudioSession: AudioSession {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
import Quick
|
||||
import Nimble
|
||||
|
||||
@testable import SwiftAudio
|
||||
@testable import SwiftAudioEx
|
||||
|
||||
|
||||
class QueueManagerTests: QuickSpec {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Quick
|
||||
import Nimble
|
||||
|
||||
@testable import SwiftAudio
|
||||
@testable import SwiftAudioEx
|
||||
|
||||
class QueuedAudioPlayerTests: QuickSpec {
|
||||
override func spec() {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftAudio
|
||||
import SwiftAudioEx
|
||||
import UIKit
|
||||
|
||||
struct Source {
|
||||
|
||||
+5
-5
@@ -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")
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol QueueManagerDelegate: class {
|
||||
protocol QueueManagerDelegate: AnyObject {
|
||||
func onReceivedFirstItem()
|
||||
func onCurrentIndexChanged(oldIndex: Int, newIndex: Int)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user