import Foundation import Darwin enum FFmpegRuntime { static func error(for app: URL) -> String? { let manifest = app.appendingPathComponent("Contents/Resources/ffmpeg-libraries.txt") let metadataError = "This app's FFmpeg library metadata is missing or invalid. Rebuild and reinstall terebi." guard let contents = try? String(contentsOf: manifest, encoding: .utf8) else { return metadataError } var paths = contents.components(separatedBy: "\n") if paths.last == "" { paths.removeLast() } let libraries: Set = ["libavformat", "libavcodec", "libavutil", "libswresample", "libswscale"] guard paths.count == libraries.count else { return metadataError } var found = Set() for path in paths { guard !path.contains("/"), !path.contains("\0"), !path.contains("\r") else { return metadataError } let parts = URL(fileURLWithPath: path).lastPathComponent.split(separator: ".", omittingEmptySubsequences: false) guard parts.count >= 3, parts.last == "dylib" else { return metadataError } let library = String(parts[0]) guard libraries.contains(library), parts.dropFirst().dropLast().allSatisfy({ !$0.isEmpty && $0.utf8.allSatisfy { (48...57).contains($0) } }), found.insert(library).inserted else { return metadataError } } let frameworks = app.appendingPathComponent("Contents/Frameworks", isDirectory: true) for filename in paths { let path = frameworks.appendingPathComponent(filename).path _ = dlerror() guard dlopen(path, RTLD_NOW | RTLD_LOCAL) != nil else { let detail = dlerror().map { String(cString: $0) } ?? "The dynamic loader could not load this library." return "This app's bundled FFmpeg libraries are missing or broken.\n\nRequired library: \(filename)\n\(detail)\n\nRebuild and reinstall terebi, or reinstall a complete bundled app." } // Deliberately never dlclose: retain successful loads until exit. } return nil } }