import AppKit import Darwin import TerebiConfiguration @main @MainActor enum TerebiCLI { static func main() async { let command: PlayerCommand do { command = try PlayerCommand.parse(Array(CommandLine.arguments.dropFirst())) } catch { fail(error.localizedDescription, code: 64) } switch command { case .help: print(PlayerCommand.usage) case .launch(let url, let newInstance, let noConfig): let configURL = PlayerConfiguration.fileURL(environment: ProcessInfo.processInfo.environment, homeDirectory: FileManager.default.homeDirectoryForCurrentUser) if !noConfig { do { _ = try PlayerConfiguration.load(from: configURL) } catch { fail(error.localizedDescription, code: 78) } } guard let executable = Bundle.main.executableURL else { fail("Could not locate the CLI executable.", code: 69) } let app = executable.resolvingSymlinksInPath().deletingLastPathComponent() .appendingPathComponent("terebi.app", isDirectory: true) if let error = FFmpegRuntime.error(for: app) { fail(error, code: 69) } let configuration = NSWorkspace.OpenConfiguration() configuration.createsNewApplicationInstance = newInstance // LaunchServices does not inherit the invoking shell's XDG environment. configuration.arguments = noConfig ? ["--no-config"] : ["--config-file", configURL.absoluteString] if newInstance, let url { configuration.arguments += ["--open-media", url.absoluteString] } do { // Launch an application, not a document, so SwiftUI creates its singleton window. _ = try await NSWorkspace.shared.openApplication(at: app, configuration: configuration) if !newInstance, let url { _ = try await NSWorkspace.shared.open([url], withApplicationAt: app, configuration: configuration) } } catch { fail("Could not launch the player: \(error.localizedDescription)", code: 69) } } } private static func fail(_ message: String, code: Int32) -> Never { FileHandle.standardError.write(Data("terebi: \(message)\n".utf8)) exit(code) } }