mod controller; mod fixtures; use std::cell::RefCell; use controller::Controller; use fixtures::{Brightness, DMXFixture, MovingHead}; type BoxedController = JsBox>; impl Finalize for Controller {} use neon::prelude::*; pub fn list_ports(mut cx: FunctionContext) -> JsResult { 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 { let path = cx.argument::(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 { let arg = cx.argument::(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::(&mut cx)?; moving_heads.push(MovingHead { start_address: head .get(&mut cx, "startAddress")? .downcast_or_throw::(&mut cx)? .value(&mut cx) as usize, pan: head .get(&mut cx, "pan")? .downcast_or_throw::(&mut cx)? .value(&mut cx), tilt: head .get(&mut cx, "tilt")? .downcast_or_throw::(&mut cx)? .value(&mut cx), brightness: { let brightness = head .get(&mut cx, "brightness")? .downcast_or_throw::(&mut cx)?; match brightness .get(&mut cx, "type")? .downcast_or_throw::(&mut cx)? .value(&mut cx) .as_str() { "off" => Brightness::Off, "dimmer" => Brightness::Dimmer( brightness .get(&mut cx, "value")? .downcast_or_throw::(&mut cx)? .value(&mut cx), ), "strobe" => Brightness::Strobe( brightness .get(&mut cx, "value")? .downcast_or_throw::(&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::(&mut cx)?; let mut vec = Vec::new(); for i in 0..4 { let v = rgbw .get(&mut cx, i)? .downcast_or_throw::(&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::(&mut cx)? .value(&mut cx) as u8, }) } let this = cx.this(); let boxed_controller = this .get(&mut cx, "_rust_ptr")? .downcast_or_throw::(&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 { let this = cx.this(); let boxed_controller = this .get(&mut cx, "_rust_ptr")? .downcast_or_throw::(&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) }