orbbec-sdk-sys 0.1.2+2.5.5

Low-level Rust bindings for https://github.com/orbbec/OrbbecSDK_v2
Documentation
use orbbec_sdk_sys::*;
use std::ffi::CStr;
use std::io::{self, Write};
use std::process;
use std::ptr;

unsafe fn from_c_str(ptr: *const std::os::raw::c_char) -> String {
    if ptr.is_null() {
        return String::from("(null)");
    }
    unsafe { CStr::from_ptr(ptr) }
        .to_string_lossy()
        .into_owned()
}

// Helper function to check for errors and exit if there is one
unsafe fn check_ob_error(err: *mut *mut ob_error) {
    unsafe {
        if !(*err).is_null() {
            let msg_ptr = ob_error_get_message(*err);
            let error_message = from_c_str(msg_ptr);
            eprintln!("Error: {}", error_message);
            ob_delete_error(*err);
            process::exit(-1);
        }
        *err = ptr::null_mut();
    }
}

fn select_index(prompt: &str, min_value: u32, max_value: u32) -> Option<u32> {
    print!("\n{} (Input device index or 'q' to exit program): ", prompt);
    io::stdout().flush().unwrap();

    loop {
        let mut input = String::new();
        io::stdin().read_line(&mut input).unwrap();
        let input = input.trim();

        if input.eq_ignore_ascii_case("q") {
            return None;
        }

        match input.parse::<u32>() {
            Ok(num) if num >= min_value && num <= max_value => {
                return Some(num);
            }
            _ => {
                print!(
                    "Invalid input, please input a number between {} and {} or 'q' to exit program: ",
                    min_value, max_value
                );
                io::stdout().flush().unwrap();
            }
        }
    }
}

unsafe fn enumerate_stream_info(sensor: *mut ob_sensor) {
    unsafe {
        let mut error: *mut ob_error = ptr::null_mut();

        // Get sensor type
        let sensor_type = ob_sensor_get_type(sensor, &mut error);
        check_ob_error(&mut error);

        // Get stream profile list
        let stream_profile_list = ob_sensor_get_stream_profile_list(sensor, &mut error);
        check_ob_error(&mut error);

        // Get stream profile count
        let stream_profile_count =
            ob_stream_profile_list_get_count(stream_profile_list, &mut error);
        check_ob_error(&mut error);

        println!("Available stream profiles: ");
        for index in 0..stream_profile_count {
            // Get stream profile
            let stream_profile =
                ob_stream_profile_list_get_profile(stream_profile_list, index as i32, &mut error);
            check_ob_error(&mut error);

            // Check sensor types (Constants are generated by bindgen)
            // Note: specific enum variant names depend on how bindgen generated them.
            // Usually: OBSensorType_OB_SENSOR_IR, etc.
            if sensor_type == OBSensorType_OB_SENSOR_IR
                || sensor_type == OBSensorType_OB_SENSOR_COLOR
                || sensor_type == OBSensorType_OB_SENSOR_DEPTH
                || sensor_type == OBSensorType_OB_SENSOR_IR_LEFT
                || sensor_type == OBSensorType_OB_SENSOR_IR_RIGHT
            {
                let stream_type = ob_stream_profile_get_type(stream_profile, &mut error);
                check_ob_error(&mut error);
                let stream_type_str = from_c_str(ob_stream_type_to_string(stream_type));

                let stream_format = ob_stream_profile_get_format(stream_profile, &mut error);
                check_ob_error(&mut error);
                let stream_format_str = from_c_str(ob_format_to_string(stream_format));

                let stream_width = ob_video_stream_profile_get_width(stream_profile, &mut error);
                check_ob_error(&mut error);

                let stream_height = ob_video_stream_profile_get_height(stream_profile, &mut error);
                check_ob_error(&mut error);

                let stream_fps = ob_video_stream_profile_get_fps(stream_profile, &mut error);
                check_ob_error(&mut error);

                println!(
                    "  {} - type: {:>4}, format: {:>4}, width: {:>4}, height: {:>4}, fps: {:>4}",
                    index,
                    stream_type_str,
                    stream_format_str,
                    stream_width,
                    stream_height,
                    stream_fps
                );
            } else if sensor_type == OBSensorType_OB_SENSOR_ACCEL {
                let stream_format = ob_stream_profile_get_format(stream_profile, &mut error);
                check_ob_error(&mut error);

                let acc_fps = ob_accel_stream_profile_get_sample_rate(stream_profile, &mut error);
                check_ob_error(&mut error);

                println!(
                    "  {} - type: {}, fps: {}",
                    index,
                    from_c_str(ob_format_to_string(stream_format)),
                    from_c_str(ob_imu_rate_type_to_string(acc_fps))
                );
            } else if sensor_type == OBSensorType_OB_SENSOR_GYRO {
                let stream_format = ob_stream_profile_get_format(stream_profile, &mut error);
                check_ob_error(&mut error);

                let gyro_fps = ob_gyro_stream_profile_get_sample_rate(stream_profile, &mut error);
                check_ob_error(&mut error);

                println!(
                    "  {} - type: {}, fps: {}",
                    index,
                    from_c_str(ob_format_to_string(stream_format)),
                    from_c_str(ob_imu_rate_type_to_string(gyro_fps))
                );
            }

            // Destroy stream profile
            ob_delete_stream_profile(stream_profile, &mut error);
            check_ob_error(&mut error);
        }

        // Destroy stream profile list
        ob_delete_stream_profile_list(stream_profile_list, &mut error);
        check_ob_error(&mut error);
    }
}

unsafe fn enumerate_sensor_info(device: *mut ob_device) {
    unsafe {
        let mut error: *mut ob_error = ptr::null_mut();

        // Get sensor list
        let sensor_list = ob_device_get_sensor_list(device, &mut error);
        check_ob_error(&mut error);

        // Get sensor count
        let sensor_count = ob_sensor_list_get_count(sensor_list, &mut error);
        check_ob_error(&mut error);

        if sensor_count == 0 {
            println!("No sensor found for the selected device!");
            ob_delete_sensor_list(sensor_list, &mut error);
            check_ob_error(&mut error);
            return;
        }

        loop {
            println!("Available sensors: ");
            for i in 0..sensor_count {
                // Get device sensor
                let sensor = ob_sensor_list_get_sensor(sensor_list, i, &mut error);
                check_ob_error(&mut error);

                // Get sensor type
                let sensor_type = ob_sensor_get_type(sensor, &mut error);
                check_ob_error(&mut error);
                let sensor_name = from_c_str(ob_sensor_type_to_string(sensor_type));

                println!("  {} - sensor name: {}", i, sensor_name);

                // Destroy sensor
                ob_delete_sensor(sensor, &mut error);
                check_ob_error(&mut error);
            }

            if let Some(index) = select_index(
                "Select a sensor to enumerate its stream profiles",
                0,
                sensor_count - 1,
            ) {
                // Get selected sensor
                let sensor = ob_sensor_list_get_sensor(sensor_list, index as u32, &mut error);
                check_ob_error(&mut error);

                // Enumerate stream information
                enumerate_stream_info(sensor);

                // Destroy sensor
                ob_delete_sensor(sensor, &mut error);
                check_ob_error(&mut error);
            } else {
                break;
            }
        }

        // Destroy sensor list
        ob_delete_sensor_list(sensor_list, &mut error);
        check_ob_error(&mut error);
    }
}

unsafe fn print_device_info(device: *mut ob_device, index: u32) {
    unsafe {
        let mut error: *mut ob_error = ptr::null_mut();

        // Get device info
        let dev_inf = ob_device_get_device_info(device, &mut error);
        check_ob_error(&mut error);

        // Get device details
        let dev_name = from_c_str(ob_device_info_get_name(dev_inf, &mut error));
        check_ob_error(&mut error);

        let dev_pid = ob_device_info_get_pid(dev_inf, &mut error);
        check_ob_error(&mut error);

        let dev_sn = from_c_str(ob_device_info_get_serial_number(dev_inf, &mut error));
        check_ob_error(&mut error);

        let conn_type = from_c_str(ob_device_info_get_connection_type(dev_inf, &mut error));
        check_ob_error(&mut error);

        println!(
            "  {} - device name: {}, device pid: {:#06x}, device sn: {}, connection type: {}",
            index, dev_name, dev_pid, dev_sn, conn_type
        );

        ob_delete_device_info(dev_inf, &mut error);
        check_ob_error(&mut error);
    }
}

fn main() {
    unsafe {
        let mut error: *mut ob_error = ptr::null_mut();

        // Get OrbbecSDK version
        let major = ob_get_major_version();
        let minor = ob_get_minor_version();
        let patch = ob_get_patch_version();
        println!("Orbbec SDK version: {}.{}.{}", major, minor, patch);

        // Create context
        let ctx = ob_create_context(&mut error);
        check_ob_error(&mut error);

        // Get device list
        let dev_list = ob_query_device_list(ctx, &mut error);
        check_ob_error(&mut error);

        // Get device count
        let dev_count = ob_device_list_get_count(dev_list, &mut error);
        check_ob_error(&mut error);

        if dev_count == 0 {
            println!("No device found! Please connect a supported device and retry this program.");

            ob_delete_device_list(dev_list, &mut error);
            check_ob_error(&mut error);

            ob_delete_context(ctx, &mut error);
            check_ob_error(&mut error);

            println!("\nPress Enter to exit.");
            let _ = io::stdin().read_line(&mut String::new());
            return;
        }

        loop {
            println!("Connected devices: ");
            for index in 0..dev_count {
                let dev = ob_device_list_get_device(dev_list, index, &mut error);
                check_ob_error(&mut error);

                print_device_info(dev, index);

                ob_delete_device(dev, &mut error);
                check_ob_error(&mut error);
            }

            let device_index =
                select_index("Select a device to enumerate its sensors", 0, dev_count - 1);

            if let Some(device_index) = device_index {
                let device = ob_device_list_get_device(dev_list, device_index as u32, &mut error);
                check_ob_error(&mut error);

                enumerate_sensor_info(device);

                ob_delete_device(device, &mut error);
                check_ob_error(&mut error);
            } else {
                break;
            }
        }

        // Cleanup
        ob_delete_device_list(dev_list, &mut error);
        check_ob_error(&mut error);

        ob_delete_context(ctx, &mut error);
        check_ob_error(&mut error);

        println!("\nProgram ended successfully. Press Enter to exit.");
        let _ = io::stdin().read_line(&mut String::new());
    }
}