Create BearWave macOS radio-first app
This commit is contained in:
76
Sources/BearWaveCore/App/AppModel.swift
Normal file
76
Sources/BearWaveCore/App/AppModel.swift
Normal file
@@ -0,0 +1,76 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user