Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
- 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`
- Run all tests: `swift test`
- Run specific test: `swift test --filter PlayolaPlayerTests/testName`
- Run specific test suite: `swift test --filter AudioNormalizationCalculatorTests`
- Generate Xcode project: `swift package generate-xcodeproj`

## Code Style Guidelines
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ PlayolaPlayer is a Swift Package Manager library that handles audio streaming, s
- Stream audio from Playola radio stations
- Schedule audio files to play at specific times
- Cache files locally with automatic cleanup
- Normalize audio volume levels
- Smooth transitions and crossfades between audio files
- Error reporting and logging
- Swift Concurrency (async/await)
Expand Down Expand Up @@ -592,7 +591,6 @@ File management ensures smooth playback:
Built on AVAudioEngine for audio processing:
- Real-time mixing of multiple audio sources
- Volume control and fading between tracks
- Audio normalization for consistent volume levels
- Session management for handling interruptions and route changes

### How Separate Files Become Continuous Radio
Expand Down Expand Up @@ -1137,7 +1135,7 @@ swift package generate-xcodeproj
swift test

# Run specific test suite
swift test --filter AudioNormalizationCalculatorTests
swift test --filter PlayolaStationPlayerTests

# Run specific test
swift test --filter PlayolaPlayerTests/testSpecificFunction
Expand Down
144 changes: 0 additions & 144 deletions Sources/PlayolaPlayer/Player/AudioNormalizationCalculator.swift

This file was deleted.

4 changes: 2 additions & 2 deletions Sources/PlayolaPlayer/Player/FileDownloaderAsync.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public actor FileDownloaderAsync {
public func download(from url: URL, to destinationURL: URL) async throws -> DownloadResult {
guard !isCancelled else { throw URLError(.cancelled) }

let configuration = URLSessionConfiguration.default
let configuration = makeTLS12Configuration()
configuration.timeoutIntervalForRequest = 30
configuration.timeoutIntervalForResource = 300
configuration.waitsForConnectivity = true
Expand Down Expand Up @@ -84,7 +84,7 @@ public actor FileDownloaderAsync {
logger: logger
)

let configuration = URLSessionConfiguration.default
let configuration = makeTLS12Configuration()
configuration.timeoutIntervalForRequest = 30
configuration.timeoutIntervalForResource = 300
configuration.waitsForConnectivity = true
Expand Down
4 changes: 2 additions & 2 deletions Sources/PlayolaPlayer/Player/ListeningSessionReporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public class ListeningSessionReporter {

init(
stationPlayer: PlayolaStationPlayer, authProvider: PlayolaAuthenticationProvider? = nil,
urlSession: URLSessionProtocol = URLSession.shared,
urlSession: URLSessionProtocol = tls12Session,
baseURL: URL = URL(string: "https://admin-api.playola.fm")!
) {
self.stationPlayer = stationPlayer
Expand Down Expand Up @@ -307,7 +307,7 @@ public class ListeningSessionReporter {
#if DEBUG
internal init(
authProvider: PlayolaAuthenticationProvider? = nil,
urlSession: URLSessionProtocol = URLSession.shared,
urlSession: URLSessionProtocol = tls12Session,
baseURL: URL = URL(string: "https://admin-api.playola.fm")!
) {
self.stationPlayer = nil
Expand Down
33 changes: 23 additions & 10 deletions Sources/PlayolaPlayer/Player/PlayolaMainMixer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by Brian D Keane on 1/6/25.
//

import AVFoundation
@preconcurrency import AVFoundation
import Foundation
import PlayolaCore
import os.log
Expand Down Expand Up @@ -138,30 +138,43 @@ open class PlayolaMainMixer: NSObject {
}

extension PlayolaMainMixer {
/// Starts the audio engine off the main thread to avoid blocking on
/// AUIOClient_StartIO during cold hardware initialization (e.g. resuming
/// from a phone-call interruption). AVAudioEngine.start() is thread-safe;
/// only the start call itself is dispatched off main.
@MainActor
public func start() throws {
public func start() async throws {
let engine = self.engine
do {
try engine.start()
} catch {
Task {
await errorReporter.reportError(
error, context: "Failed to start audio engine",
level: .critical)
try await withCheckedThrowingContinuation {
(continuation: CheckedContinuation<Void, Error>) in
DispatchQueue.global(qos: .userInitiated).async {
do {
try engine.start()
continuation.resume()
} catch {
continuation.resume(throwing: error)
}
}
}
} catch {
await errorReporter.reportError(
error, context: "Failed to start audio engine",
level: .critical)
throw error
}
}

@MainActor
public func restartEngine() throws {
public func restartEngine() async throws {
os_log("Restarting audio engine", log: PlayolaMainMixer.logger, type: .info)

if engine.isRunning {
engine.stop()
}

engine.prepare()
try start()
try await start()
}

public var isEngineRunning: Bool {
Expand Down
6 changes: 3 additions & 3 deletions Sources/PlayolaPlayer/Player/PlayolaStationPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public enum StationPlayerError: Error, LocalizedError {
/// ```
@MainActor
final public class PlayolaStationPlayer: ObservableObject {
var baseUrl = URL(string: "https://admin-api.playola.fm/v1")!
var baseUrl = URL(string: "https://admin-api.playola.fm")!
@Published public var stationId: String?
private var interruptedStationId: String?
var currentSchedule: Schedule?
Expand Down Expand Up @@ -402,7 +402,7 @@ final public class PlayolaStationPlayer: ObservableObject {
let url = createScheduleURL(for: stationId)

do {
let (data, response) = try await URLSession.shared.data(from: url)
let (data, response) = try await tls12Session.data(from: url)
let httpResponse = try validateHTTPResponse(response, url: url)
try await validateStatusCode(httpResponse, data: data, stationId: stationId)

Expand Down Expand Up @@ -739,7 +739,7 @@ final public class PlayolaStationPlayer: ObservableObject {
Task { @MainActor in
do {
try await PlayolaMainMixer.shared.audioSessionManager.activate()
try PlayolaMainMixer.shared.restartEngine()
try await PlayolaMainMixer.shared.restartEngine()
try await self.play(stationId: stationToResume)
} catch {
os_log(
Expand Down
Loading
Loading