39 lines
1.5 KiB
Swift
39 lines
1.5 KiB
Swift
import AppKit
|
|
import Darwin
|
|
|
|
@main
|
|
@MainActor
|
|
enum TerebiBootstrap {
|
|
static func main() {
|
|
let app = Bundle.main.bundleURL
|
|
if let error = FFmpegRuntime.error(for: app) {
|
|
fail(error)
|
|
}
|
|
let payload = app.appendingPathComponent("Contents/Frameworks/libterebi-player.dylib")
|
|
guard let library = dlopen(payload.path, RTLD_NOW | RTLD_LOCAL) else {
|
|
let detail = dlerror().map { String(cString: $0) } ?? "The dynamic loader could not load the player."
|
|
fail("Could not load the player: \(detail)\n\nPlayer library: \(payload.path)\nRebuild and reinstall Terebi.")
|
|
}
|
|
guard let entry = dlsym(library, "terebi_app_main") else {
|
|
fail("The player library is missing its application entry point. Rebuild and reinstall Terebi.")
|
|
}
|
|
// Keep the declared app executable alive so LaunchServices retains its identity.
|
|
typealias PlayerMain = @convention(c) () -> Void
|
|
unsafeBitCast(entry, to: PlayerMain.self)()
|
|
}
|
|
|
|
private static func fail(_ message: String) -> Never {
|
|
FileHandle.standardError.write(Data("terebi: \(message)\n".utf8))
|
|
let application = NSApplication.shared
|
|
application.setActivationPolicy(.regular)
|
|
application.activate(ignoringOtherApps: true)
|
|
let alert = NSAlert()
|
|
alert.alertStyle = .critical
|
|
alert.messageText = "Terebi could not start"
|
|
alert.informativeText = message
|
|
alert.addButton(withTitle: "Quit")
|
|
alert.runModal()
|
|
exit(69)
|
|
}
|
|
}
|