ddc-node-rs 2.0.0

DDC/CI high level library for Rust (cross platform)
Documentation
use crate::data::{Continuous, Display, NonContinuous, Table, VcpReadValue, VcpWriteValue};
use ddc::{Ddc, DdcHost, DdcTable};
use ddc_hi::{Backend, FeatureCode, Query};
use mccs_db::ValueType;
use std::io::{Error, ErrorKind};

pub fn get_displays(needs_caps: bool, query: Query) -> Result<Vec<(usize, Display)>, Error> {
    Display::enumerate()
        .into_iter()
        .enumerate()
        .map(|(index, mut display)| {
            if needs_caps && display.info.backend == Backend::WinApi {
                display
                    .update_capabilities()
                    .map(|_| (index, display))
                    .map_err(|err| Error::new(ErrorKind::TimedOut, err.to_string()))
            } else {
                Ok((index, display))
            }
        })
        .filter(|display| {
            if let &Ok(ref display) = display {
                query.matches(&display.1.info)
            } else {
                true
            }
        })
        .collect()
}

pub fn get_display(needs_caps: bool, display_index: usize) -> Result<(usize, Display), Error> {
    get_displays(needs_caps, Query::Any)?
        .into_iter()
        .filter(|&(index, _)| index == display_index)
        .next()
        .ok_or(Error::new(
            ErrorKind::Unsupported,
            format!("There is no display at index: {}", display_index),
        ))
}

pub fn get_vcp_feature(
    display_index: usize,
    feature_code: FeatureCode,
) -> Result<VcpReadValue, Error> {
    let mut display = get_display(true, display_index)?.1;
    display
        .update_from_ddc()
        .map_err(|error| Error::new(ErrorKind::TimedOut, error.to_string()))?;
    let feature = display.info.mccs_database.get(feature_code);
    let handle = &mut display.handle;
    if let Some(feature) = feature {
        match feature.ty {
            ValueType::Unknown => {
                let vcp_feature_value = handle
                    .get_vcp_feature(feature_code)
                    .map_err(|error| Error::new(ErrorKind::TimedOut, error.to_string()))?;
                let current_value = vcp_feature_value.value();
                let maximum_value = vcp_feature_value.maximum();
                handle.sleep();
                Ok(VcpReadValue::Continuous(Continuous {
                    current_value,
                    maximum_value,
                }))
            }
            ValueType::Continuous {
                interpretation: _interpretation,
            } => {
                let vcp_feature_value = handle
                    .get_vcp_feature(feature_code)
                    .map_err(|error| Error::new(ErrorKind::TimedOut, error.to_string()))?;
                let current_value = vcp_feature_value.value();
                let maximum_value = vcp_feature_value.maximum();
                handle.sleep();
                Ok(VcpReadValue::Continuous(Continuous {
                    current_value,
                    maximum_value,
                }))
            }
            ValueType::NonContinuous {
                ref values,
                interpretation: _interpretation,
            } => {
                let vcp_feature_value = handle
                    .get_vcp_feature(feature_code)
                    .map_err(|error| Error::new(ErrorKind::TimedOut, error.to_string()))?;
                let mut current_value = (vcp_feature_value.value(), None);
                let possible_values = values.clone();
                if let Some(&Some(ref name)) = values.get(&(vcp_feature_value.value() as u8)) {
                    current_value.1 = Some(name.clone());
                }
                handle.sleep();
                Ok(VcpReadValue::NonContinuous(NonContinuous {
                    current_value,
                    possible_values,
                }))
            }
            ValueType::Table {
                interpretation: _interpretation,
            } => {
                let vcp_feature_value = handle
                    .table_read(feature_code)
                    .map_err(|error| Error::new(ErrorKind::TimedOut, error.to_string()))?;
                handle.sleep();
                Ok(VcpReadValue::Table(Table {
                    current_data: vcp_feature_value,
                }))
            }
        }
    } else {
        match handle.table_read(feature_code) {
            Ok(vcp_feature_value) => {
                handle.sleep();
                Ok(VcpReadValue::Table(Table {
                    current_data: vcp_feature_value,
                }))
            }
            Err(_) => {
                let vcp_feature_value = handle
                    .get_vcp_feature(feature_code)
                    .map_err(|error| Error::new(ErrorKind::TimedOut, error.to_string()))?;
                let current_value = vcp_feature_value.value();
                let maximum_value = vcp_feature_value.maximum();
                handle.sleep();
                Ok(VcpReadValue::Continuous(Continuous {
                    current_value,
                    maximum_value,
                }))
            }
        }
    }
}

pub fn set_vcp_feature(
    display_index: usize,
    feature_code: FeatureCode,
    value: VcpWriteValue,
) -> Result<(), Error> {
    let mut display = get_display(true, display_index)?.1;

    match value {
        VcpWriteValue::Single(value) => {
            let result = display
                .handle
                .set_vcp_feature(feature_code, value)
                .map_err(|error| Error::new(ErrorKind::TimedOut, error.to_string()))?;
            display.handle.sleep();
            Ok(result)
        }
        VcpWriteValue::Bytes(bytes, offset) => {
            let result = display
                .handle
                .table_write(feature_code, offset, &bytes)
                .map_err(|error| Error::new(ErrorKind::TimedOut, error.to_string()))?;
            display.handle.sleep();
            Ok(result)
        }
    }
}