eye 0.5.0

Cross platform camera capture and control
Documentation
use std::ops::Index;

use eye_hal::control::Descriptor as ControlDescriptor;
use eye_hal::control::State as ControlState;
use eye_hal::error::{Error, ErrorKind, Result};
use eye_hal::platform::Context as PlatformContext;
use eye_hal::platform::{Device as PlatformDevice, Stream as PlatformStream};
use eye_hal::stream::Descriptor as StreamDescriptor;
use eye_hal::traits::{Context, Device as DeviceTrait, Stream as StreamTrait};

use crate::colorconvert;

/// A transparent wrapper type for native platform devices.
pub struct Device<'a> {
    // hardware abstraction layer (HAL)
    pub hal: Box<dyn DeviceTrait<'a> + 'a>,
}

impl<'a> Device<'a> {
    fn new(hal: impl DeviceTrait<'a> + 'a + Send) -> Result<Self> {
        let cc = colorconvert::Device::new(PlatformDevice::Custom(Box::new(hal)))?;
        Ok(Device { hal: Box::new(cc) })
    }

    pub fn with_index(index: usize) -> Result<Self> {
        let ctx = PlatformContext::default();
        let devices = ctx.devices()?;
        let uri = if let Some(desc) = devices.get(index) {
            &desc.uri
        } else {
            return Err(Error::new(ErrorKind::Other, "invalid index"));
        };
        let hal = ctx.open_device(uri)?;

        Self::new(hal)
    }

    pub fn with_uri<S: AsRef<str>>(uri: S) -> Result<Self> {
        let uri = uri.as_ref();
        let ctx = PlatformContext::default();
        let hal = ctx.open_device(uri)?;

        Self::new(hal)
    }

    pub fn streams(&'a self) -> Result<impl Iterator<Item=Stream<'a>>> {
        let streams = self.hal.streams()?;
        Ok(Streams {
            dev: &*self.hal,
            streams,
        })
    }

    pub fn controls(&'a self) -> Result<Controls<&dyn DeviceTrait>> {
        let descs = self.hal.controls()?;
        Ok(Controls {
            dev: &*self.hal,
            descs,
        })
    }

    pub fn controls_mut(&'a mut self) -> Result<Controls<&mut dyn DeviceTrait>> {
        let descs = self.hal.controls()?;
        Ok(Controls {
            dev: &mut *self.hal,
            descs,
        })
    }
}

pub struct Streams<'a> {
    dev: &'a dyn DeviceTrait<'a>,
    streams: Vec<StreamDescriptor>,
    index: usize,
}

impl<'a> Streams<'a> {
    pub fn filter<P>(self, predicate: P) -> Self
    where
        P: FnMut(&StreamDescriptor) -> bool,
    {
        Streams {
            dev: self.dev,
            streams: self.streams.into_iter().filter(predicate).collect(),
            index: 0,
        }
    }

    pub fn reduce<F>(self, f: F) -> Option<Stream<'a>>
    where
        F: FnMut(StreamDescriptor, StreamDescriptor) -> StreamDescriptor,
    {
        match self.streams.into_iter().reduce(f) {
            Some(desc) => Some(Stream {
                dev: self.dev,
                desc,
            }),
            None => None,
        }
    }
}

impl<'a> Iterator for Streams<'a> {
    type Item = Stream<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index >= self.streams.len() {
            None
        } else {
            Some(self.streams.remove(0))
        }
    }
}

pub struct Stream<'a> {
    dev: &'a dyn DeviceTrait<'a>,
    desc: StreamDescriptor,
}

impl<'a> Stream<'a> {
    pub fn start(self) -> Result<impl StreamTrait<'a>> {
        self.dev.start_stream(&self.desc)
    }
}

pub struct Controls<D> {
    dev: D,
    descs: Vec<ControlDescriptor>,
}

impl<'a, D> Controls<D>
where
    D: AsRef<dyn DeviceTrait<'a>>,
{
    pub fn filter<P>(self, predicate: P) -> Self
    where
        P: FnMut(&ControlDescriptor) -> bool,
    {
        Controls {
            dev: self.dev,
            descs: self.descs.into_iter().filter(predicate).collect(),
        }
    }

    pub fn find<P>(self, predicate: P) -> Option<Control<D>>
    where
        P: FnMut(&ControlDescriptor) -> bool,
    {
        match self.descs.into_iter().find(predicate) {
            Some(desc) => Some(Control {
                dev: self.dev,
                desc,
            }),
            None => None,
        }
    }
}

impl<'a, D> Controls<D>
where
    D: AsMut<dyn DeviceTrait<'a>>,
{
    pub fn find_mut<P>(self, predicate: P) -> Option<Control<D>>
    where
        P: FnMut(&ControlDescriptor) -> bool,
    {
        match self.descs.into_iter().find(predicate) {
            Some(desc) => Some(Control {
                dev: self.dev,
                desc,
            }),
            None => None,
        }
    }
}

pub struct Control<D> {
    dev: D,
    desc: ControlDescriptor,
}

impl<'a, D> Control<D>
where
    D: AsRef<dyn DeviceTrait<'a>>,
{
    pub fn read(&self) -> Result<ControlState> {
        self.dev.as_ref().control(self.desc.id)
    }
}

impl<'a, D> Control<D>
where
    D: AsMut<dyn DeviceTrait<'a>>,
{
    pub fn write(&mut self, state: ControlState) -> Result<()> {
        self.dev.as_mut().set_control(self.desc.id, &state)
    }
}