use deimos::{
calc::*,
controller::channel::{Endpoint, Msg},
dispatcher::fmt_time,
};
use serde::{Deserialize, Serialize};
use tracing::info;
use std::{
collections::BTreeMap,
ops::Range,
time::{Duration, SystemTime},
};
use controller::context::ControllerCtx;
use deimos::*;
fn main() {
let rate_hz = 4.0;
let dt_ns = (1e9_f64 / rate_hz).ceil() as u32;
let termination_criteria = Some(Termination::Timeout(Duration::from_millis(500)));
let mut ctx = ControllerCtx::default();
ctx.dt_ns = dt_ns;
ctx.termination_criteria = termination_criteria;
ctx.user_ctx
.insert("speaker_prefix".to_owned(), "foobar".to_owned());
let mut controller = Controller::new(ctx);
controller.clear_sockets();
controller.add_calc("speaker", Box::new(Speaker::new("time channel")));
controller.add_calc(
"listener",
Box::new(Listener::new("speaker.y", "time channel")),
);
{
let serialized_controller = serde_json::to_string_pretty(&controller).unwrap();
let _: Controller = serde_json::from_str(&serialized_controller).unwrap();
}
controller.run(&None, None).unwrap();
}
#[derive(Serialize, Deserialize, Default, Debug)]
pub struct Speaker {
channel_name: String,
save_outputs: bool,
#[serde(skip)]
endpoint: Endpoint,
prefix: String,
#[serde(skip)]
output_index: usize,
}
impl Speaker {
pub fn new(channel_name: &str) -> Self {
let output_index = usize::MAX;
Self {
channel_name: channel_name.to_owned(),
save_outputs: false,
endpoint: Endpoint::default(),
prefix: "".to_owned(),
output_index,
}
}
}
#[typetag::serde]
impl Calc for Speaker {
fn init(
&mut self,
ctx: ControllerCtx,
_input_indices: Vec<usize>,
output_range: Range<usize>,
) -> Result<(), String> {
self.output_index = output_range.clone().next().unwrap();
self.endpoint = ctx.source_endpoint(&self.channel_name);
self.prefix = ctx.user_ctx.get("speaker_prefix").unwrap().to_owned();
Ok(())
}
fn terminate(&mut self) -> Result<(), String> {
self.output_index = usize::MAX;
self.endpoint = Endpoint::default();
Ok(())
}
fn eval(&mut self, _tape: &mut [f64]) -> Result<(), String> {
let msg = Msg::Str(format!(
"{} at {:?}",
&self.prefix,
fmt_time(SystemTime::now())
));
self.endpoint.tx().try_send(msg).unwrap();
Ok(())
}
fn get_input_map(&self) -> BTreeMap<CalcInputName, FieldName> {
BTreeMap::new()
}
fn update_input_map(&mut self, field: &str, _source: &str) -> Result<(), String> {
Err(format!("Unrecognized field {field}")) }
calc_config!();
calc_input_names!();
calc_output_names!(y);
}
#[derive(Serialize, Deserialize, Default, Debug)]
pub struct Listener {
channel_name: String,
save_outputs: bool,
#[serde(skip)]
endpoint: Endpoint,
#[serde(skip)]
output_index: usize,
}
impl Listener {
pub fn new(_input_name: &str, channel_name: &str) -> Self {
let output_index = usize::MAX;
Self {
channel_name: channel_name.to_owned(),
save_outputs: false,
endpoint: Endpoint::default(),
output_index,
}
}
}
#[typetag::serde]
impl Calc for Listener {
fn init(
&mut self,
ctx: ControllerCtx,
_input_indices: Vec<usize>,
output_range: Range<usize>,
) -> Result<(), String> {
self.output_index = output_range.clone().next().unwrap();
self.endpoint = ctx.sink_endpoint(&self.channel_name);
Ok(())
}
fn terminate(&mut self) -> Result<(), String> {
self.output_index = usize::MAX;
self.endpoint = Endpoint::default();
Ok(())
}
fn eval(&mut self, _tape: &mut [f64]) -> Result<(), String> {
let msg = match self.endpoint.rx().try_recv() {
Ok(x) => x,
Err(_) => return Ok(()),
};
match msg {
Msg::Str(s) => {
info!("{s}");
}
x => panic!("Unexpected message type: {x:?}"),
}
Ok(())
}
fn get_input_map(&self) -> BTreeMap<CalcInputName, FieldName> {
BTreeMap::new()
}
fn update_input_map(&mut self, field: &str, _source: &str) -> Result<(), String> {
Err(format!("Unrecognized field {field}")) }
calc_config!();
calc_input_names!();
calc_output_names!(y);
}