77 lines
2.7 KiB
Swift
77 lines
2.7 KiB
Swift
import AppKit
|
|
import Foundation
|
|
import Observation
|
|
|
|
@Observable
|
|
@MainActor
|
|
public final class AppModel {
|
|
public let settings: SettingsStore
|
|
public let library: StationLibrary
|
|
public let playback: PlaybackController
|
|
let artwork: StationArtworkLoader
|
|
private let nowPlayingArtwork: NowPlayingArtworkResolver
|
|
|
|
public convenience init() {
|
|
self.init(settings: SettingsStore(), persistence: PersistenceStore())
|
|
}
|
|
|
|
init(
|
|
settings: SettingsStore = SettingsStore(),
|
|
persistence: PersistenceStore = PersistenceStore()
|
|
) {
|
|
self.settings = settings
|
|
let client = RadioBrowserClient(baseURL: settings.baseURL, cacheDirectory: persistence.apiCacheDirectory)
|
|
library = StationLibrary(client: client, persistence: persistence)
|
|
let artworkLoader = StationArtworkLoader(cacheDirectory: persistence.cacheDirectory)
|
|
artwork = artworkLoader
|
|
nowPlayingArtwork = NowPlayingArtworkResolver(cacheDirectory: persistence.cacheDirectory, faviconLoader: artworkLoader)
|
|
playback = PlaybackController(artworkProvider: { [weak nowPlayingArtwork] station, artist, title in
|
|
nowPlayingArtwork?.resolve(artist: artist, title: title, station: station) ?? BearWaveAssets.image(named: "bearwave") ?? NSImage()
|
|
})
|
|
nowPlayingArtwork.onArtworkLoaded = { [weak playback] in
|
|
playback?.refreshNowPlaying()
|
|
}
|
|
playback.onMetadataChanged = { [weak nowPlayingArtwork] artist, title, station in
|
|
nowPlayingArtwork?.fetchArtwork(artist: artist, title: title, station: station)
|
|
}
|
|
playback.volume = library.volume
|
|
library.updateBaseURL(settings.baseURL)
|
|
}
|
|
|
|
public func start() async {
|
|
await library.load(.top)
|
|
if settings.resumeOnLaunch, let station = library.resumeStation() {
|
|
play(station)
|
|
}
|
|
}
|
|
|
|
public func play(_ station: RadioStation) {
|
|
library.recordPlayback(station)
|
|
playback.play(station)
|
|
nowPlayingArtwork.fetchArtwork(
|
|
artist: playback.currentTrackArtist.isEmpty ? nil : playback.currentTrackArtist,
|
|
title: playback.currentTrackTitle.isEmpty ? nil : playback.currentTrackTitle,
|
|
station: station
|
|
)
|
|
}
|
|
|
|
public func resumeLastStation() {
|
|
guard let station = library.resumeStation() else { return }
|
|
play(station)
|
|
}
|
|
|
|
public func setVolume(_ value: Double) {
|
|
playback.volume = value
|
|
library.saveVolume(value)
|
|
}
|
|
|
|
public func applySettings() {
|
|
library.updateBaseURL(settings.baseURL)
|
|
}
|
|
|
|
public func quit() {
|
|
playback.stop()
|
|
nowPlayingArtwork.fetchArtwork(artist: nil, title: nil, station: nil)
|
|
}
|
|
}
|