99 lines
2.7 KiB
Swift
99 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
|
||
|
|
}
|