diff --git a/App/Sources/Coordinator.swift b/App/Sources/Coordinator.swift index 6ce64de..efff146 100644 --- a/App/Sources/Coordinator.swift +++ b/App/Sources/Coordinator.swift @@ -41,6 +41,12 @@ final class Coordinator { outputs.applyLaunchRoutes() audio.applyLaunchRoutes() applyLoginItemArgument() + if let index = ProcessInfo.processInfo.arguments.firstIndex(of: "--load-scene"), + index + 1 < ProcessInfo.processInfo.arguments.count { + let name = ProcessInfo.processInfo.arguments[index + 1] + if let scene = store.scenes.first(where: { $0.name == name }) { loadScene(scene) } + else { Log.remote.error("--load-scene: no scene named \(name, privacy: .public)") } + } statusTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in MainActor.assumeIsolated { self?.sendStatus() } @@ -81,6 +87,7 @@ final class Coordinator { /// Shows a source on a node's screen. func show(_ assignment: VideoAssignment, onNode name: String) { + Log.remote.info("UI: show \(assignment.source.ndiName, privacy: .public) on \(name, privacy: .public)/\(assignment.screen.name, privacy: .public)") var config = desiredConfig(forNode: name) config.video.removeAll { $0.screen == assignment.screen } config.video.append(assignment) @@ -90,6 +97,7 @@ final class Coordinator { } func stop(_ screen: ScreenRef, onNode name: String) { + Log.remote.info("UI: stop \(name, privacy: .public)/\(screen.name, privacy: .public)") var config = desiredConfig(forNode: name) config.video.removeAll { $0.screen == screen } live.nodes[name] = config @@ -105,7 +113,7 @@ final class Coordinator { private func nodeConnected(_ node: NodeBrowser.Node) { if let desired = live.nodes[node.name] { node.send(.apply(desired)) - Log.ndi.info("Sent configuration to \(node.name, privacy: .public)") + Log.remote.info("Sent configuration to \(node.name, privacy: .public): \(desired.video.count) video") } else { adoptWhenStatusArrives(node) } @@ -117,6 +125,7 @@ final class Coordinator { try? await Task.sleep(for: .seconds(1)) guard let self, live.nodes[node.name] == nil else { return } if let config = node.status?.config { + Log.remote.info("Adopted configuration of \(node.name, privacy: .public): \(config.video.count) video") live.nodes[node.name] = config store.saveLiveState(live) return @@ -128,6 +137,7 @@ final class Coordinator { // MARK: - Node: commands from the control private func handle(_ message: RemoteMessage) { + Log.remote.info("Command: \(String(describing: message).prefix(200), privacy: .public)") switch message { case .apply(let config): outputs.apply(config.video) @@ -206,6 +216,7 @@ final class Coordinator { } private func markModified() { + Log.remote.debug("Live state saved: local \(self.live.local.video.count) video, nodes \(self.live.nodes.mapValues(\.video.count), privacy: .public)") if live.sceneID != nil { live.modified = true } store.saveLiveState(live) } diff --git a/App/Sources/MusubiApp.swift b/App/Sources/MusubiApp.swift index f29a36e..da6c17e 100644 --- a/App/Sources/MusubiApp.swift +++ b/App/Sources/MusubiApp.swift @@ -38,4 +38,5 @@ final class AppDelegate: NSObject, NSApplicationDelegate { enum Log { static let ndi = Logger(subsystem: "studio.zielke.musubi", category: "ndi") static let audio = Logger(subsystem: "studio.zielke.musubi", category: "audio") + static let remote = Logger(subsystem: "studio.zielke.musubi", category: "scene") }