Skip to content

Commit eae75ea

Browse files
authored
Merge pull request #92 from playola-radio/develop
0.17.0
2 parents eaa9487 + d90d818 commit eae75ea

13 files changed

Lines changed: 71 additions & 713 deletions

CLAUDE.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
- Build example app for simulator: `cd PlayolaPlayerExample && xcodebuild -project PlayolaPlayerExample.xcodeproj -scheme PlayolaPlayerExample -destination 'platform=iOS Simulator,id=F8C70EF6-2658-40DE-ABB2-13B4EA4CFBD3' build -quiet`
66
- Run all tests: `swift test`
77
- Run specific test: `swift test --filter PlayolaPlayerTests/testName`
8-
- Run specific test suite: `swift test --filter AudioNormalizationCalculatorTests`
98
- Generate Xcode project: `swift package generate-xcodeproj`
109

1110
## Code Style Guidelines

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ PlayolaPlayer is a Swift Package Manager library that handles audio streaming, s
1111
- Stream audio from Playola radio stations
1212
- Schedule audio files to play at specific times
1313
- Cache files locally with automatic cleanup
14-
- Normalize audio volume levels
1514
- Smooth transitions and crossfades between audio files
1615
- Error reporting and logging
1716
- Swift Concurrency (async/await)
@@ -592,7 +591,6 @@ File management ensures smooth playback:
592591
Built on AVAudioEngine for audio processing:
593592
- Real-time mixing of multiple audio sources
594593
- Volume control and fading between tracks
595-
- Audio normalization for consistent volume levels
596594
- Session management for handling interruptions and route changes
597595

598596
### How Separate Files Become Continuous Radio
@@ -1137,7 +1135,7 @@ swift package generate-xcodeproj
11371135
swift test
11381136

11391137
# Run specific test suite
1140-
swift test --filter AudioNormalizationCalculatorTests
1138+
swift test --filter PlayolaStationPlayerTests
11411139

11421140
# Run specific test
11431141
swift test --filter PlayolaPlayerTests/testSpecificFunction

Sources/PlayolaPlayer/Player/AudioNormalizationCalculator.swift

Lines changed: 0 additions & 144 deletions
This file was deleted.

Sources/PlayolaPlayer/Player/FileDownloaderAsync.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public actor FileDownloaderAsync {
3434
public func download(from url: URL, to destinationURL: URL) async throws -> DownloadResult {
3535
guard !isCancelled else { throw URLError(.cancelled) }
3636

37-
let configuration = URLSessionConfiguration.default
37+
let configuration = makeTLS12Configuration()
3838
configuration.timeoutIntervalForRequest = 30
3939
configuration.timeoutIntervalForResource = 300
4040
configuration.waitsForConnectivity = true
@@ -84,7 +84,7 @@ public actor FileDownloaderAsync {
8484
logger: logger
8585
)
8686

87-
let configuration = URLSessionConfiguration.default
87+
let configuration = makeTLS12Configuration()
8888
configuration.timeoutIntervalForRequest = 30
8989
configuration.timeoutIntervalForResource = 300
9090
configuration.waitsForConnectivity = true

Sources/PlayolaPlayer/Player/ListeningSessionReporter.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public class ListeningSessionReporter {
6666

6767
init(
6868
stationPlayer: PlayolaStationPlayer, authProvider: PlayolaAuthenticationProvider? = nil,
69-
urlSession: URLSessionProtocol = URLSession.shared,
69+
urlSession: URLSessionProtocol = tls12Session,
7070
baseURL: URL = URL(string: "https://admin-api.playola.fm")!
7171
) {
7272
self.stationPlayer = stationPlayer
@@ -307,7 +307,7 @@ public class ListeningSessionReporter {
307307
#if DEBUG
308308
internal init(
309309
authProvider: PlayolaAuthenticationProvider? = nil,
310-
urlSession: URLSessionProtocol = URLSession.shared,
310+
urlSession: URLSessionProtocol = tls12Session,
311311
baseURL: URL = URL(string: "https://admin-api.playola.fm")!
312312
) {
313313
self.stationPlayer = nil

Sources/PlayolaPlayer/Player/PlayolaMainMixer.swift

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Created by Brian D Keane on 1/6/25.
66
//
77

8-
import AVFoundation
8+
@preconcurrency import AVFoundation
99
import Foundation
1010
import PlayolaCore
1111
import os.log
@@ -138,30 +138,43 @@ open class PlayolaMainMixer: NSObject {
138138
}
139139

140140
extension PlayolaMainMixer {
141+
/// Starts the audio engine off the main thread to avoid blocking on
142+
/// AUIOClient_StartIO during cold hardware initialization (e.g. resuming
143+
/// from a phone-call interruption). AVAudioEngine.start() is thread-safe;
144+
/// only the start call itself is dispatched off main.
141145
@MainActor
142-
public func start() throws {
146+
public func start() async throws {
147+
let engine = self.engine
143148
do {
144-
try engine.start()
145-
} catch {
146-
Task {
147-
await errorReporter.reportError(
148-
error, context: "Failed to start audio engine",
149-
level: .critical)
149+
try await withCheckedThrowingContinuation {
150+
(continuation: CheckedContinuation<Void, Error>) in
151+
DispatchQueue.global(qos: .userInitiated).async {
152+
do {
153+
try engine.start()
154+
continuation.resume()
155+
} catch {
156+
continuation.resume(throwing: error)
157+
}
158+
}
150159
}
160+
} catch {
161+
await errorReporter.reportError(
162+
error, context: "Failed to start audio engine",
163+
level: .critical)
151164
throw error
152165
}
153166
}
154167

155168
@MainActor
156-
public func restartEngine() throws {
169+
public func restartEngine() async throws {
157170
os_log("Restarting audio engine", log: PlayolaMainMixer.logger, type: .info)
158171

159172
if engine.isRunning {
160173
engine.stop()
161174
}
162175

163176
engine.prepare()
164-
try start()
177+
try await start()
165178
}
166179

167180
public var isEngineRunning: Bool {

Sources/PlayolaPlayer/Player/PlayolaStationPlayer.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public enum StationPlayerError: Error, LocalizedError {
5959
/// ```
6060
@MainActor
6161
final public class PlayolaStationPlayer: ObservableObject {
62-
var baseUrl = URL(string: "https://admin-api.playola.fm/v1")!
62+
var baseUrl = URL(string: "https://admin-api.playola.fm")!
6363
@Published public var stationId: String?
6464
private var interruptedStationId: String?
6565
var currentSchedule: Schedule?
@@ -402,7 +402,7 @@ final public class PlayolaStationPlayer: ObservableObject {
402402
let url = createScheduleURL(for: stationId)
403403

404404
do {
405-
let (data, response) = try await URLSession.shared.data(from: url)
405+
let (data, response) = try await tls12Session.data(from: url)
406406
let httpResponse = try validateHTTPResponse(response, url: url)
407407
try await validateStatusCode(httpResponse, data: data, stationId: stationId)
408408

@@ -739,7 +739,7 @@ final public class PlayolaStationPlayer: ObservableObject {
739739
Task { @MainActor in
740740
do {
741741
try await PlayolaMainMixer.shared.audioSessionManager.activate()
742-
try PlayolaMainMixer.shared.restartEngine()
742+
try await PlayolaMainMixer.shared.restartEngine()
743743
try await self.play(stationId: stationToResume)
744744
} catch {
745745
os_log(

0 commit comments

Comments
 (0)