realsense-rust 1.3.0

High-level RealSense library in Rust
Documentation
//! An example to list all possible stream profiles from all connected RealSense devices.

use anyhow::{ensure, Result};
use realsense_rust::{
    context::Context,
    device::Device,
    kind::{Rs2CameraInfo, Rs2Format, Rs2StreamKind},
    sensor::Sensor,
    stream_profile::StreamProfile,
};
use std::collections::{HashMap, HashSet};

/// Helper function to get device info or return "N/A" if not available
fn get_device_info(device: &Device, info_param: Rs2CameraInfo) -> String {
    device
        .info(info_param)
        .map(|s| s.to_str().unwrap_or("N/A").to_string())
        .unwrap_or_else(|| "N/A".to_string())
}

/// Helper function to get sensor info or return "N/A" if not available
fn get_sensor_info(sensor: &Sensor, info_param: Rs2CameraInfo) -> String {
    sensor
        .info(info_param)
        .map(|s| s.to_str().unwrap_or("N/A").to_string())
        .unwrap_or_else(|| "N/A".to_string())
}

/// Format resolution for video streams, return "N/A" for non-video streams
fn format_resolution(profile: &StreamProfile) -> String {
    // Try to get video stream profile data if it's a video stream
    match profile.kind() {
        Rs2StreamKind::Depth
        | Rs2StreamKind::Color
        | Rs2StreamKind::Infrared
        | Rs2StreamKind::Fisheye => {
            // For video streams, try to get intrinsics to determine resolution
            match profile.intrinsics() {
                Ok(intrinsics) => format!("{}x{}", intrinsics.width(), intrinsics.height()),
                Err(_) => "Default".to_string(),
            }
        }
        _ => "N/A".to_string(),
    }
}

/// Format the stream kind for display
fn format_stream_kind(kind: Rs2StreamKind) -> &'static str {
    match kind {
        Rs2StreamKind::Depth => "Depth",
        Rs2StreamKind::Color => "Color",
        Rs2StreamKind::Infrared => "Infrared",
        Rs2StreamKind::Fisheye => "Fisheye",
        Rs2StreamKind::Gyro => "Gyroscope",
        Rs2StreamKind::Accel => "Accelerometer",
        Rs2StreamKind::Pose => "Pose",
        Rs2StreamKind::Confidence => "Confidence",
        _ => "Other",
    }
}

/// Format the stream format for display
fn format_stream_format(format: Rs2Format) -> String {
    format!("{:?}", format)
}

fn main() -> Result<()> {
    println!("=== RealSense Stream Profile Enumeration ===\n");

    // Create context and query all connected devices
    let context = Context::new()?;
    let devices = context.query_devices(HashSet::new());

    ensure!(
        !devices.is_empty(),
        "No RealSense devices found. Please connect a device and try again."
    );

    println!("Found {} device(s)\n", devices.len());

    for (device_idx, device) in devices.iter().enumerate() {
        // Display device information
        let device_name = get_device_info(device, Rs2CameraInfo::Name);
        let serial_number = get_device_info(device, Rs2CameraInfo::SerialNumber);
        let firmware_version = get_device_info(device, Rs2CameraInfo::FirmwareVersion);
        let usb_type = get_device_info(device, Rs2CameraInfo::UsbTypeDescriptor);

        // Skip platform cameras and other non-RealSense devices
        if device_name.contains("Platform Camera") || !device_name.contains("RealSense") {
            println!(
                "Device #{}: {} (Skipping - not a RealSense device)",
                device_idx + 1,
                device_name
            );
            continue;
        }

        println!("Device #{}: {}", device_idx + 1, device_name);
        println!("  Serial Number: {}", serial_number);
        println!("  Firmware: {}", firmware_version);
        println!("  USB Type: {}", usb_type);
        if !usb_type.contains("3.") {
            eprintln!("\tNote: USB 3.0 connection required for full streaming capabilities. Current connection: {}", usb_type);
            eprintln!("\tPlease connect the RealSense module to a USB 3.0 port.");
        }
        println!("  Sensors:");

        // Get all sensors for this device
        let sensors = device.sensors();

        for (sensor_idx, sensor) in sensors.iter().enumerate() {
            let sensor_name = get_sensor_info(sensor, Rs2CameraInfo::Name);
            println!("    Sensor #{}: {}", sensor_idx + 1, sensor_name);

            // Get all stream profiles for this sensor
            let stream_profiles = sensor.stream_profiles();

            if stream_profiles.is_empty() {
                println!("      No stream profiles available");
                continue;
            }

            println!("      Available Streams:");
            println!(
                "        {:<15} {:<8} {:<15} {:<12} {:<8} {:<10} {:<8}",
                "Type", "Index", "Format", "Resolution", "FPS", "Unique ID", "Default"
            );
            println!("        {}", "-".repeat(82));

            // Group stream profiles by type for better organization
            let mut streams_by_kind: HashMap<Rs2StreamKind, Vec<&StreamProfile>> = HashMap::new();

            for profile in &stream_profiles {
                streams_by_kind
                    .entry(profile.kind())
                    .or_default()
                    .push(profile);
            }

            // Display streams organized by type
            for (kind, profiles) in streams_by_kind {
                for profile in profiles {
                    // Skip profiles that might cause issues (like unsupported platform cameras)
                    let stream_type = format_stream_kind(kind);
                    let format_str = format_stream_format(profile.format());
                    let resolution_str = format_resolution(profile);
                    let default_marker = if profile.is_default() { "" } else { "" };

                    println!(
                        "        {:<15} {:<8} {:<15} {:<12} {:<8} {:<10} {:<8}",
                        stream_type,
                        profile.index(),
                        format_str,
                        resolution_str,
                        profile.framerate(),
                        profile.unique_id(),
                        default_marker
                    );
                }
            }
            println!();
        }
        println!();
    }

    // Summary statistics
    let total_sensors: usize = devices.iter().map(|d| d.sensors().len()).sum();
    let total_streams: usize = devices
        .iter()
        .map(|d| {
            d.sensors()
                .iter()
                .map(|s| s.stream_profiles().len())
                .sum::<usize>()
        })
        .sum();

    println!("=== Summary ===");
    println!("Total Devices: {}", devices.len());
    println!("Total Sensors: {}", total_sensors);
    println!("Total Stream Profiles: {}", total_streams);

    Ok(())
}