///|
/// Return the default capture mode used when native listings omit mode details.
fn default_mode() -> CaptureMode {
{ width: 1_280, height: 720, fps: 30, pixel_format: Mjpeg }
}
///|
/// Infer a facing value from the native camera display name.
fn infer_facing(name : String) -> Facing {
let lower = name.to_lower()
if lower.contains("rear") || lower.contains("back") {
Back
} else if lower.contains("front") ||
lower.contains("facetime") ||
lower.contains("built-in") {
Front
} else {
External
}
}
///|
/// Build a stable camera id from its compact discovery index.
fn camera_id(index : Int) -> String {
"camera-\{index}"
}
///|
/// Parse a native camera listing into camera descriptors.
///
/// Each non-empty line is treated as one camera name. Native platform APIs
/// usually omit capture modes at this discovery stage, so parsed devices
/// receive a conservative `1280x720@30 MJPEG` default mode and `torch=false`.
///
/// # Example
/// ```mbt check
/// test {
/// let devices = @camera.CameraDevice::parse_listing(
/// "Front Camera\nUSB Camera\n",
/// )
/// inspect(devices.length(), content="2")
/// inspect(devices[0].label(), content="front:Front Camera")
/// inspect(devices[1].label(), content="external:USB Camera")
/// }
/// ```
pub fn CameraDevice::parse_listing(output : String) -> Array[CameraDevice] {
let devices : Array[CameraDevice] = []
for line in output.split("\n").to_array() {
let name = line.trim().to_owned()
if name != "" {
devices.push({
id: camera_id(devices.length()),
name,
facing: infer_facing(name),
mode: default_mode(),
torch: false,
})
}
}
devices
}
///|
/// List camera devices visible to the current native platform.
///
/// Discovery is intentionally lightweight: the backend uses platform APIs to
/// enumerate camera names and turns them into portable descriptors. Applications
/// that need negotiated frame formats can use these descriptors as a first
/// discovery pass before opening a platform-specific capture session.
///
/// # Example
/// ```mbt check
/// test {
/// for device in @camera.CameraDevice::list() {
/// ignore(device.label())
/// }
/// }
/// ```
pub fn CameraDevice::list() -> Array[CameraDevice] {
CameraDevice::parse_listing(native_camera_listing())
}