broken changes
This commit is contained in:
@@ -65,6 +65,7 @@ struct SongDragReference: Codable, Sendable {
|
||||
@Published var activeSection = "Library"
|
||||
@Published var studio = StudioSettings() { didSet { applyStudioSettings(save:true,previous:oldValue) } }
|
||||
let backgroundDeck = BackgroundDeck()
|
||||
let dj = DJSystem()
|
||||
var backgroundAutomationReady = false
|
||||
var backgroundPlaybackObserver: AnyCancellable?
|
||||
var backgroundHandoff: Task<Void,Never>?
|
||||
@@ -717,6 +718,7 @@ struct LibraryView: View {
|
||||
|
||||
private var selectedSong: Song? { model.songs.first { $0.id == selected } }
|
||||
private var workspace: some View {
|
||||
VSplitView {
|
||||
HSplitView {
|
||||
sidebar.frame(minWidth:220,idealWidth:240,maxWidth:260)
|
||||
VStack(spacing:0) {
|
||||
@@ -752,6 +754,9 @@ struct LibraryView: View {
|
||||
footer.padding(.horizontal,18).padding(.vertical,8)
|
||||
}.frame(minWidth:780)
|
||||
}
|
||||
.frame(minHeight:400)
|
||||
DJConsole(model:model,system:model.dj).frame(minHeight:400,idealHeight:470)
|
||||
}
|
||||
.background(StudioTheme.frame)
|
||||
.tint(.accentColor)
|
||||
.focusedSceneValue(\.nameReinterpretation,NameReinterpretationCommands(perform:{beginReinterpretation()},enabled:["Library","Singer Songs"].contains(source) && (selectedSong != nil || !tableSelection.isEmpty)))
|
||||
|
||||
+14
-3
@@ -2,6 +2,8 @@ import SwiftUI
|
||||
import AVFoundation
|
||||
import CryptoKit
|
||||
import CoreImage
|
||||
import AudioToolbox
|
||||
import CoreAudio
|
||||
|
||||
/// CDG follows consumed source frames, so tempo adjustment preserves graphics timing.
|
||||
@MainActor final class Player: ObservableObject {
|
||||
@@ -81,12 +83,20 @@ import CoreImage
|
||||
private let videoContext = CIContext()
|
||||
private var mixURL: URL { waveformCacheDirectory.deletingLastPathComponent().appendingPathComponent("GlobalMixer.json") }
|
||||
private var restoringMix = true
|
||||
private var persistsMix = true
|
||||
func routeOutput(_ device: AudioDeviceID) throws {
|
||||
guard let unit = engine.outputNode.audioUnit else { throw LibraryError.message("Audio output unavailable") }
|
||||
let running = engine.isRunning;engine.stop();var value = device
|
||||
let result = AudioUnitSetProperty(unit,kAudioOutputUnitProperty_CurrentDevice,kAudioUnitScope_Global,0,&value,UInt32(MemoryLayout.size(ofValue:value)))
|
||||
guard result == noErr else { throw LibraryError.message("Audio routing failed (\(result))") }
|
||||
if running { try engine.start() }
|
||||
}
|
||||
struct GlobalMix: Codable, Equatable {
|
||||
var volume: Double; var low: Double; var mid: Double; var high: Double; var filter: Double; var enabled: Bool
|
||||
}
|
||||
var globalMix: GlobalMix { .init(volume:volume,low:lowGain,mid:midGain,high:highGain,filter:filter,enabled:toneEnabled) }
|
||||
private func saveMix() {
|
||||
guard !restoringMix, let data = try? JSONEncoder().encode(globalMix) else { return }
|
||||
guard persistsMix,!restoringMix, let data = try? JSONEncoder().encode(globalMix) else { return }
|
||||
try? FileManager.default.createDirectory(at:mixURL.deletingLastPathComponent(),withIntermediateDirectories:true)
|
||||
try? data.write(to:mixURL,options:.atomic)
|
||||
onGlobalMixChanged?(globalMix)
|
||||
@@ -131,10 +141,11 @@ import CoreImage
|
||||
private var cdg = Data()
|
||||
private var decoder = CDGDecoder()
|
||||
private var timer: Timer?
|
||||
init(waveformCacheDirectory: URL? = nil) {
|
||||
init(waveformCacheDirectory: URL? = nil, persistsMix: Bool = true) {
|
||||
self.persistsMix = persistsMix
|
||||
self.waveformCacheDirectory = waveformCacheDirectory ?? FileManager.default.urls(for:.applicationSupportDirectory,in:.userDomainMask)[0].appendingPathComponent("KJamsClone/Waveforms")
|
||||
engine.attach(node);engine.attach(effect);engine.attach(tone)
|
||||
if let data = try? Data(contentsOf:mixURL),let mix = try? JSONDecoder().decode(GlobalMix.self,from:data) {
|
||||
if persistsMix,let data = try? Data(contentsOf:mixURL),let mix = try? JSONDecoder().decode(GlobalMix.self,from:data) {
|
||||
volume = min(1,max(0,mix.volume));lowGain = min(12,max(-12,mix.low));midGain = min(12,max(-12,mix.mid));highGain = min(12,max(-12,mix.high));filter = min(1,max(-1,mix.filter));toneEnabled = mix.enabled
|
||||
}
|
||||
restoringMix = false;updateTone()
|
||||
|
||||
Reference in New Issue
Block a user