feat: select Miruro playback and caption providers

This commit is contained in:
2026-10-22 18:45:14 +02:00
parent 4576080955
commit 80d9e705e5
10 changed files with 561 additions and 76 deletions
@@ -10,14 +10,19 @@ public struct PlayerConfiguration: Equatable, Sendable {
public var automaticQuality: Bool
public var snapToEdges: Bool
public var compactTitleProgress: CompactTitleProgress
public var miruroVideoProvider: String
public var miruroCaptionProvider: String
public var keys: KeyBindings
public init(showBufferInfo: Bool = false, automaticQuality: Bool = false, snapToEdges: Bool = true,
compactTitleProgress: CompactTitleProgress = .time, keys: KeyBindings = KeyBindings()) {
compactTitleProgress: CompactTitleProgress = .time, miruroVideoProvider: String = "",
miruroCaptionProvider: String = "", keys: KeyBindings = KeyBindings()) {
self.showBufferInfo = showBufferInfo
self.automaticQuality = automaticQuality
self.snapToEdges = snapToEdges
self.compactTitleProgress = compactTitleProgress
self.miruroVideoProvider = miruroVideoProvider
self.miruroCaptionProvider = miruroCaptionProvider
self.keys = keys
}
@@ -28,6 +33,9 @@ public struct PlayerConfiguration: Equatable, Sendable {
var lines = [
"[playback]",
"automatic_quality = \(defaults.automaticQuality)",
"", "[miruro]",
"video_provider = \"\(defaults.miruroVideoProvider)\"",
"caption_provider = \"\(defaults.miruroCaptionProvider)\"",
"", "[ui]",
"buffer_info = \(defaults.showBufferInfo)",
"compact_snap_to_edges = \(defaults.snapToEdges)",
@@ -85,6 +93,8 @@ public struct PlayerConfiguration: Equatable, Sendable {
automaticQuality: values.playback?.automaticQuality ?? false,
snapToEdges: values.ui?.compactSnapToEdges ?? true,
compactTitleProgress: values.ui?.compactTitleProgress ?? .time,
miruroVideoProvider: values.miruro?.videoProvider ?? "",
miruroCaptionProvider: values.miruro?.captionProvider ?? "",
keys: try KeyBindings(overrides: values.keys?.overrides ?? [:]))
} catch {
throw ConfigurationError(message: "\(url.path): \(diagnostic(for: error, data: data))")
@@ -143,10 +153,11 @@ public struct PlayerConfiguration: Equatable, Sendable {
let playback: PlaybackConfiguration?
let ui: UIConfiguration?
let keys: KeysConfiguration?
let miruro: MiruroConfiguration?
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: SettingKey.self)
try validate(container, allowed: ["playback", "ui", "keys"])
try validate(container, allowed: ["playback", "ui", "keys", "miruro"])
if container.contains(SettingKey("playback")) {
playback = try PlaybackConfiguration(container: container.nestedContainer(keyedBy: SettingKey.self, forKey: SettingKey("playback")))
} else { playback = nil }
@@ -156,6 +167,9 @@ public struct PlayerConfiguration: Equatable, Sendable {
if container.contains(SettingKey("keys")) {
keys = try KeysConfiguration(container: container.nestedContainer(keyedBy: SettingKey.self, forKey: SettingKey("keys")))
} else { keys = nil }
if container.contains(SettingKey("miruro")) {
miruro = try MiruroConfiguration(container: container.nestedContainer(keyedBy: SettingKey.self, forKey: SettingKey("miruro")))
} else { miruro = nil }
}
}
@@ -168,6 +182,29 @@ public struct PlayerConfiguration: Equatable, Sendable {
}
}
private struct MiruroConfiguration {
let videoProvider: String?
let captionProvider: String?
init(container: KeyedDecodingContainer<SettingKey>) throws {
try validate(container, allowed: ["video_provider", "caption_provider"])
videoProvider = try Self.provider("video_provider", in: container)
captionProvider = try Self.provider("caption_provider", in: container)
}
private static func provider(_ name: String, in container: KeyedDecodingContainer<SettingKey>) throws -> String? {
let value = try container.decodeIfPresent(String.self, forKey: SettingKey(name))
if let value {
guard value.utf8.count <= 128, value.utf8.allSatisfy({
(65...90).contains($0) || (97...122).contains($0) || (48...57).contains($0) || $0 == 95 || $0 == 45
}) else {
throw ConfigurationError(message: "miruro.\(name): Expected an empty string (Auto) or up to 128 ASCII letters, digits, underscores or hyphens.")
}
}
return value
}
}
private struct UIConfiguration {
let bufferInfo: Bool?
let compactSnapToEdges: Bool?