1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
//! A cross-platform laser DAC detection and streaming API.
pub extern crate ether_dream;
pub mod dac;
#[cfg(feature = "ffi")]
pub mod ffi;
#[cfg(feature = "ilda-idtf")]
pub mod ilda_idtf;
pub mod point;
pub mod stream;
pub mod util;
pub use dac::{DetectDacs, DetectDacsAsync, DetectedDac, DetectedDacCallback, Id as DacId};
pub use point::{Point, RawPoint};
pub use stream::frame::Frame;
pub use stream::frame::Stream as FrameStream;
pub use stream::raw::Stream as RawStream;
pub use stream::raw::{Buffer, StreamError, StreamErrorAction};
use std::io;
use std::sync::Arc;
use std::time::Duration;
/// A general API that allows for detecting and enumerating laser DACs on a network and
/// establishing new streams of communication with them.
pub struct Api {
inner: Arc<Inner>,
}
// The inner state of the `Api` that can be easily shared between laser threads in an `Arc`.
//
// This is useful for allowing streams to re-scan and find their associated DAC in the case it
// drops out for some reason.
pub(crate) struct Inner;
impl Api {
/// Instantiate the laser API.
pub fn new() -> Self {
Api {
inner: Arc::new(Inner),
}
}
/// An iterator yielding laser DACs available on the system as they are discovered.
///
/// Currently, the only laser protocol supported is the ether dream protocol. Thus, this
/// enumerates ether dream DACs that are discovered on the LAN.
///
/// **Note** that the produced iterator will iterate forever and never terminate unless
/// `set_timeout` is called on the returned `DetectDacs` instance.
pub fn detect_dacs(&self) -> io::Result<DetectDacs> {
self.inner.detect_dacs()
}
/// Block and wait until the DAC with the given `Id` is detected.
pub fn detect_dac(&self, id: DacId) -> io::Result<DetectedDac> {
self.inner.detect_dac(id)
}
/// Spawn a thread for DAC detection.
///
/// Calls the given `callback` with broadcasts as they are received.
///
/// The thread is closed when the returned `DetectDacsAsync` instance is dropped.
pub fn detect_dacs_async<F>(
&self,
timeout: Option<Duration>,
callback: F,
) -> io::Result<DetectDacsAsync>
where
F: 'static + DetectedDacCallback + Send,
{
self.inner.detect_dacs_async(timeout, callback)
}
/// Begin building a new laser frame stream.
///
/// The stream will call the `render` function each time new points are needed to feed the
/// laser DAC buffer. The rate at which this will be called depends on the `point_hz`,
/// `frame_hz` and the `latency_points`.
pub fn new_frame_stream<M, F>(&self, model: M, render: F) -> stream::frame::Builder<M, F>
where
F: stream::frame::RenderFn<M>,
{
let api_inner = self.inner.clone();
let builder = Default::default();
let frame_hz = None;
let interpolation_conf = Default::default();
let enable_optimisations = stream::DEFAULT_ENABLE_OPTIMISATIONS;
let enable_draw_reorder = stream::DEFAULT_ENABLE_DRAW_REORDER;
let process_raw = stream::frame::default_process_raw_fn;
let stream_error = stream::raw::default_stream_error_fn;
stream::frame::Builder {
api_inner,
builder,
model,
render,
process_raw,
stream_error,
frame_hz,
interpolation_conf,
enable_optimisations,
enable_draw_reorder,
}
}
/// Begin building a new laser raw stream.
///
/// The raw stream will call the given `render` function with a request for as many points as
/// the DAC currently might need to fill the buffer based on the stream latency.
pub fn new_raw_stream<M, F>(&self, model: M, render: F) -> stream::raw::Builder<M, F>
where
F: stream::raw::RenderFn<M>,
{
let api_inner = self.inner.clone();
let builder = Default::default();
let stream_error = stream::raw::default_stream_error_fn;
stream::raw::Builder {
api_inner,
builder,
model,
render,
stream_error,
}
}
}
impl Inner {
/// See the `Api::detect_dacs` docs.
pub(crate) fn detect_dacs(&self) -> io::Result<DetectDacs> {
dac::detect_dacs()
}
/// Block and wait until the DAC with the given `Id` is detected.
pub(crate) fn detect_dac(&self, id: DacId) -> io::Result<DetectedDac> {
for res in self.detect_dacs()? {
let dac = res?;
if dac.id() == id {
return Ok(dac);
}
}
unreachable!("DAC detection iterator should never return `None`")
}
/// See the `Api::detect_dacs_async` docs.
fn detect_dacs_async<F>(
&self,
timeout: Option<Duration>,
callback: F,
) -> io::Result<DetectDacsAsync>
where
F: 'static + DetectedDacCallback + Send,
{
dac::detect_dacs_async(timeout, callback)
}
}
impl AsRef<Point> for Point {
fn as_ref(&self) -> &Point {
self
}
}