lsl 0.1.1

Lab streaming layer (liblsl) bindings for rust.
Documentation
/** Example program that shows several advanced capabilities when reading data. */
use lsl;
use lsl::Pullable; // trait used by the inlet // for user input
use std::io;
use std::vec;

fn main() -> Result<(), lsl::Error> {
    println!("Resolving EEG stream...");
    // First we're resolving a stream that matches a given predicate (see function documentation).
    // You're not limited to the default meta-data here but can query against anything under desc/
    // Some applications may use a finite timeout, e.g., 30 seconds, and some may also use a short
    // 2-3s timeout (assuming that the stream is already present), but allow more than one return
    // value and then to warn the user if there were multiple matching streams present.
    let res = lsl::resolve_bypred("name='BioSemi' and type='EEG'", 1, lsl::FOREVER)?;

    // Next we're creating an inlet to read from it. Let's say this is a real-time processing tool,
    // and we have no use for more than 10 seconds of data backlog accumulating in case our program
    // stalls for a while, so we set the max buffer length to 10s. We'll also ask that the data be
    // transmitted in chunks of 20 samples at a time, e.g., to save network bandwidth.
    let inl = lsl::StreamInlet::new(&res[0], 10, 8, true)?;

    // now that we have the inlet we can use it to retrieve the full StreamInfo object from it
    // (since custom meta-data could in theory be gigabytes, this is not transmitted by the resolve
    // call)
    let mut info = inl.info(5.0)?;

    // we can now traverse the extended meta-data of the stream to get the information we need
    // (usually we'll want at least the channel labels, which are typically stored as below)
    println!("\nThe channel labels were:");
    let mut cursor = info.desc().child("channels").child("channel");
    while cursor.is_valid() {
        print!("  {}", cursor.child_value_named("label"));
        cursor = cursor.next_sibling();
    }
    // ... alternatively we could get an XML string and parse it using some other crate
    println!("\n\nThe StreamInfo's full XML dump is: {}", info.to_xml()?);

    println!("Press [Enter] to continue");
    let mut ret = String::new();
    io::stdin().read_line(&mut ret).expect("stdin read error");

    // let's also suppose that we want to sync the received data's time stamps with our local_clock(),
    // e.g., to relate the data to some local events. We can enable that via post-processing, but
    // see also the inlet's time_correction() method for the manual way that gives you full control
    inl.set_postprocessing(&[
        lsl::ProcessingOption::ClockSync,
        lsl::ProcessingOption::Dejitter,
    ])?;

    // now we're reading data in a loop and print it as we go
    println!("Reading data...");
    let mut sample = vec::Vec::<f32>::new();
    loop {
        // do a blocking read (with finite timeout) to get the next successive sample and its
        // time stamp; we read into a pre-allocated buffer (which will be right-sized by the pull
        // call) since that's more efficient for high-bandwidth data.
        let ts = inl.pull_sample_buf(&mut sample, 5.0)?;

        // if we're using a finite timeout we need to check if the timestamp is nonzero (zero means
        // no new data)
        if ts != 0.0 {
            println!("got {:?} at time {}", sample, ts);
        } else {
            println!("got no new data, waiting some more...")
        }
    }
}