feat(*): subsonic client with avfoundation playback and apple music ui

This commit is contained in:
hh committed 2026-09-22 06:44:44 +02:00
commit e5bb559d7f
93 files changed
+7517

No files matched your search

@@ -0,0 +1,79 @@
import Foundation
public struct ResourceRequest: Hashable, Sendable {
public var url: URL
public var headers: [String: String]
public var expiresAt: Date?
public init(url: URL, headers: [String: String] = [:], expiresAt: Date? = nil) {
self.url = url
self.headers = headers
self.expiresAt = expiresAt
}
}
public struct StreamRequest: Hashable, Sendable {
public var resource: ResourceRequest
public var format: AudioFormat?
public init(resource: ResourceRequest, format: AudioFormat?) {
self.resource = resource
self.format = format
}
}
public struct Cursor: Hashable, Codable, Sendable {
public let raw: String
public init(_ raw: String) {
self.raw = raw
}
}
public struct Annotation: Hashable, Codable, Sendable {
public var favoritedAt: Date?
public var playCount: Int
public var lastPlayedAt: Date?
public init(favoritedAt: Date? = nil, playCount: Int = 0, lastPlayedAt: Date? = nil) {
self.favoritedAt = favoritedAt
self.playCount = playCount
self.lastPlayedAt = lastPlayedAt
}
}
public enum Entity: Sendable {
case artist(Artist)
case album(Album)
case track(Track)
case playlist(Playlist, entries: [PlaylistEntry])
case station(RadioStation)
}
public enum Change: Sendable {
case upsert(Entity)
case remove(EntityKind, EntityID)
case annotate(EntityID, Annotation)
case checkpoint(Cursor)
}
public enum SourceError: Error {
case cannotCalculateChanges
case notFound
}
public protocol LibrarySource: Sendable {
var id: SourceID { get }
var name: String { get }
func changes(since cursor: Cursor?) -> AsyncThrowingStream<Change, Error>
func stream(for track: EntityID) async throws -> StreamRequest
func artwork(_ id: EntityID, pixelSize: Int) async throws -> ResourceRequest
}
public protocol Starring: LibrarySource {
func setFavorite(_ isFavorite: Bool, for id: EntityID, kind: EntityKind) async throws
}
public protocol Scrobbling: LibrarySource {
func scrobble(_ track: EntityID, at date: Date, submission: Bool) async throws
}