Files
Amphlify/Packages/AmphlifyKit/Sources/Playback/PlaybackModel.swift
T

89 lines
2.5 KiB
Swift

import Domain
import Foundation
public struct QueueItem: Identifiable, Hashable, Codable, Sendable {
public let id: UUID
public let track: Track
public init(id: UUID = UUID(), track: Track) {
self.id = id
self.track = track
}
}
public enum RepeatMode: String, Codable, Sendable, CaseIterable {
case off, all, one
}
public enum PlaybackCommand: Codable, Sendable {
case play
case pause
case togglePlayPause
case seek(to: TimeInterval)
case next
case previous
case setQueue(tracks: [Track], startIndex: Int, shuffled: Bool)
case insertNext([Track])
case insertLast([Track])
case jump(to: QueueItem.ID)
case move(item: QueueItem.ID, after: QueueItem.ID?)
case remove(QueueItem.ID)
case clearUpcoming
case setShuffle(Bool)
case setRepeat(RepeatMode)
}
public struct PlaybackAnchor: Hashable, Sendable {
public var position: TimeInterval
public var instant: ContinuousClock.Instant
public var rate: Double
public init(position: TimeInterval, instant: ContinuousClock.Instant, rate: Double) {
self.position = position
self.instant = instant
self.rate = rate
}
public func position(at now: ContinuousClock.Instant) -> TimeInterval {
let elapsed = now - instant
let seconds = Double(elapsed.components.seconds) + Double(elapsed.components.attoseconds) / 1e18
return position + seconds * rate
}
}
public enum PlaybackStatus: String, Sendable {
case stopped, paused, playing
}
public struct PlaybackState: Hashable, Sendable {
public var history: [QueueItem] = []
public var current: QueueItem?
public var upcoming: [QueueItem] = []
public var status: PlaybackStatus = .stopped
public var anchor = PlaybackAnchor(position: 0, instant: .now, rate: 0)
public var isShuffled = false
public var repeatMode: RepeatMode = .off
public init() {}
}
public enum OutputEvent: Sendable {
case finished(QueueItem.ID)
case failed(QueueItem.ID)
case anchor(QueueItem.ID, position: TimeInterval, rate: Double)
}
public protocol OutputEngine: Sendable {
var events: AsyncStream<OutputEvent> { get }
func load(_ item: QueueItem, at position: TimeInterval) async
func prepare(_ item: QueueItem?) async
func play() async
func pause() async
func seek(to position: TimeInterval) async
func stop() async
}
public extension OutputEngine {
func prepare(_: QueueItem?) async {}
}