rainbow-dragon/Sources/ForgeCamera/CameraDriver.swift

98 lines
2.7 KiB
Swift

import Foundation
import ForgeGrade
import ForgeColor
public enum CameraVendor: String, Sendable, Codable {
case arri
case red
case sony
case simulated
}
public enum MetadataField: String, Sendable, Codable, CaseIterable {
case clipName
case exposureIndex
case whiteBalance
case tint
case fps
case timecode
case lens
}
/// What a camera can accept / report. Drivers declare, grade pipeline adapts.
public struct CameraCapabilities: Sendable {
public var vendor: CameraVendor
/// Camera applies ASC CDL natively (RED IPP2, ARRI ALF4). If false, CDL must be baked into LUT.
public var supportsNativeCDL: Bool
/// Accepted 3D LUT lattice sizes.
public var lut3dSizes: [Int]
public var metadataFields: [MetadataField]
public init(vendor: CameraVendor, supportsNativeCDL: Bool, lut3dSizes: [Int], metadataFields: [MetadataField]) {
self.vendor = vendor
self.supportsNativeCDL = supportsNativeCDL
self.lut3dSizes = lut3dSizes
self.metadataFields = metadataFields
}
}
public enum ConnectionStatus: String, Sendable, Equatable {
case disconnected
case connecting
case connected
}
public struct CameraMetadata: Sendable, Equatable {
public var exposureIndex: Int?
public var whiteBalance: Int?
public var tint: Int?
public var fps: Double?
public var timecode: String?
public var lens: String?
public init(
exposureIndex: Int? = nil, whiteBalance: Int? = nil, tint: Int? = nil,
fps: Double? = nil, timecode: String? = nil, lens: String? = nil
) {
self.exposureIndex = exposureIndex
self.whiteBalance = whiteBalance
self.tint = tint
self.fps = fps
self.timecode = timecode
self.lens = lens
}
}
public struct CameraState: Sendable, Equatable {
public var connection: ConnectionStatus
public var isRecording: Bool
public var clipName: String?
public var metadata: CameraMetadata?
public init(
connection: ConnectionStatus,
isRecording: Bool = false,
clipName: String? = nil,
metadata: CameraMetadata? = nil
) {
self.connection = connection
self.isRecording = isRecording
self.clipName = clipName
self.metadata = metadata
}
}
public enum CameraError: Error, Equatable {
case connectionFailed(String)
case pushFailed(String)
case unsupportedLook(String)
}
/// Hardware seam. One driver instance per physical camera.
public protocol CameraDriver: Actor {
nonisolated var capabilities: CameraCapabilities { get }
nonisolated var state: AsyncStream<CameraState> { get }
func connect() async throws
func disconnect() async
func push(look: FlattenedLook) async throws
}