195 lines
5.6 KiB
Rust
195 lines
5.6 KiB
Rust
mod controller;
|
|
mod fixtures;
|
|
|
|
use std::cell::RefCell;
|
|
|
|
use controller::Controller;
|
|
use fixtures::{Brightness, DMXFixture, MovingHead};
|
|
|
|
type BoxedController = JsBox<RefCell<Controller>>;
|
|
impl Finalize for Controller {}
|
|
|
|
use neon::prelude::*;
|
|
|
|
pub fn list_ports(mut cx: FunctionContext) -> JsResult<JsArray> {
|
|
let array = cx.empty_array();
|
|
|
|
if let Ok(ports) = serialport::available_ports() {
|
|
for (i, port) in ports.iter().enumerate() {
|
|
let port_name = cx.string(&port.port_name);
|
|
array.set(&mut cx, i as u32, port_name)?;
|
|
}
|
|
}
|
|
|
|
Ok(array)
|
|
}
|
|
|
|
pub fn open_output(mut cx: FunctionContext) -> JsResult<JsObject> {
|
|
let path = cx.argument::<JsString>(0)?;
|
|
let path = path.value(&mut cx);
|
|
|
|
let obj = cx.empty_object();
|
|
let success_string;
|
|
|
|
match Controller::new(path) {
|
|
Ok(controller) => {
|
|
success_string = cx.string("success");
|
|
|
|
let boxed_controller = cx.boxed(RefCell::new(controller));
|
|
obj.set(&mut cx, "_rust_ptr", boxed_controller)?;
|
|
|
|
let set_output_function = JsFunction::new(&mut cx, set_output)?;
|
|
obj.set(&mut cx, "set", set_output_function)?;
|
|
|
|
let close_function = JsFunction::new(&mut cx, close_output)?;
|
|
obj.set(&mut cx, "close", close_function)?;
|
|
}
|
|
Err(e) => {
|
|
success_string = cx.string("error");
|
|
|
|
let error_message = cx.string(e.to_string());
|
|
obj.set(&mut cx, "message", error_message)?;
|
|
}
|
|
}
|
|
|
|
obj.set(&mut cx, "type", success_string)?;
|
|
|
|
Ok(obj)
|
|
}
|
|
|
|
fn set_output(mut cx: FunctionContext) -> JsResult<JsObject> {
|
|
let arg = cx.argument::<JsArray>(0)?;
|
|
|
|
let mut moving_heads = Vec::with_capacity(4);
|
|
|
|
for i in 0..arg.len(&mut cx) {
|
|
// why isn't neon-serde maintained anymore? T_T
|
|
|
|
let head = arg
|
|
.get(&mut cx, i)?
|
|
.downcast_or_throw::<JsObject, _>(&mut cx)?;
|
|
|
|
moving_heads.push(MovingHead {
|
|
start_address: head
|
|
.get(&mut cx, "startAddress")?
|
|
.downcast_or_throw::<JsNumber, _>(&mut cx)?
|
|
.value(&mut cx) as usize,
|
|
|
|
pan: head
|
|
.get(&mut cx, "pan")?
|
|
.downcast_or_throw::<JsNumber, _>(&mut cx)?
|
|
.value(&mut cx),
|
|
|
|
tilt: head
|
|
.get(&mut cx, "tilt")?
|
|
.downcast_or_throw::<JsNumber, _>(&mut cx)?
|
|
.value(&mut cx),
|
|
|
|
brightness: {
|
|
let brightness = head
|
|
.get(&mut cx, "brightness")?
|
|
.downcast_or_throw::<JsObject, _>(&mut cx)?;
|
|
|
|
match brightness
|
|
.get(&mut cx, "type")?
|
|
.downcast_or_throw::<JsString, _>(&mut cx)?
|
|
.value(&mut cx)
|
|
.as_str()
|
|
{
|
|
"off" => Brightness::Off,
|
|
"dimmer" => Brightness::Dimmer(
|
|
brightness
|
|
.get(&mut cx, "value")?
|
|
.downcast_or_throw::<JsNumber, _>(&mut cx)?
|
|
.value(&mut cx),
|
|
),
|
|
"strobe" => Brightness::Strobe(
|
|
brightness
|
|
.get(&mut cx, "value")?
|
|
.downcast_or_throw::<JsNumber, _>(&mut cx)?
|
|
.value(&mut cx),
|
|
),
|
|
"switch" => Brightness::Switch,
|
|
s => {
|
|
let err = cx.string(format!("Invalid brightness type: {}", s));
|
|
return cx.throw(err);
|
|
}
|
|
}
|
|
},
|
|
|
|
rgbw: {
|
|
let rgbw = head
|
|
.get(&mut cx, "rgbw")?
|
|
.downcast_or_throw::<JsArray, _>(&mut cx)?;
|
|
|
|
let mut vec = Vec::new();
|
|
|
|
for i in 0..4 {
|
|
let v = rgbw
|
|
.get(&mut cx, i)?
|
|
.downcast_or_throw::<JsNumber, _>(&mut cx)?
|
|
.value(&mut cx) as u8;
|
|
|
|
vec.push(v);
|
|
}
|
|
|
|
(vec[0], vec[1], vec[2], vec[3])
|
|
},
|
|
|
|
speed: head
|
|
.get(&mut cx, "speed")?
|
|
.downcast_or_throw::<JsNumber, _>(&mut cx)?
|
|
.value(&mut cx) as u8,
|
|
})
|
|
}
|
|
|
|
let this = cx.this();
|
|
let boxed_controller = this
|
|
.get(&mut cx, "_rust_ptr")?
|
|
.downcast_or_throw::<BoxedController, _>(&mut cx)?;
|
|
|
|
let boxed_controller = boxed_controller.borrow_mut();
|
|
{
|
|
let mut state = boxed_controller.state.lock().unwrap();
|
|
|
|
for head in moving_heads {
|
|
head.render(&mut state.data);
|
|
}
|
|
}
|
|
|
|
let obj = cx.empty_object();
|
|
|
|
let success_text = cx.string("success".to_string());
|
|
obj.set(&mut cx, "type", success_text)?;
|
|
|
|
Ok(obj)
|
|
}
|
|
|
|
fn close_output(mut cx: FunctionContext) -> JsResult<JsObject> {
|
|
let this = cx.this();
|
|
|
|
let boxed_controller = this
|
|
.get(&mut cx, "_rust_ptr")?
|
|
.downcast_or_throw::<BoxedController, _>(&mut cx)?;
|
|
|
|
let obj = cx.empty_object();
|
|
|
|
let success_string;
|
|
|
|
match boxed_controller.borrow_mut().stop() {
|
|
Ok(()) => {
|
|
success_string = cx.string("success");
|
|
}
|
|
Err(e) => {
|
|
success_string = cx.string("error");
|
|
|
|
let error_message = cx.string(e.to_string());
|
|
obj.set(&mut cx, "message", error_message)?;
|
|
}
|
|
}
|
|
|
|
obj.set(&mut cx, "type", success_string)?;
|
|
|
|
Ok(obj)
|
|
}
|