Lua support: add script handling class with basic I/O
The relevant functions are called and the return types and sizes verified. The API for the user is not implemented yet.
This commit is contained in:
parent
942f66f7df
commit
62bbff481c
|
@ -4,3 +4,9 @@ pub const SAMP_RATE: f32 = 48000.0;
|
|||
|
||||
// samples read from stdin per update
|
||||
pub const SAMPLES_PER_UPDATE: usize = BLOCK_LEN/2;
|
||||
|
||||
// LED configuration
|
||||
pub const NUM_STRIPS: usize = 8;
|
||||
pub const NUM_LEDS_PER_STRIP: usize = 16;
|
||||
|
||||
pub const NUM_LEDS_TOTAL: usize = NUM_STRIPS * NUM_LEDS_PER_STRIP;
|
||||
|
|
27
src/main.rs
27
src/main.rs
|
@ -5,30 +5,30 @@ use std::collections::VecDeque;
|
|||
|
||||
use byteorder::{NativeEndian, ReadBytesExt};
|
||||
|
||||
use mlua::Lua;
|
||||
|
||||
mod signal_processing;
|
||||
mod config;
|
||||
mod userscript;
|
||||
|
||||
use crate::signal_processing::SignalProcessing;
|
||||
use crate::userscript::UserScript;
|
||||
|
||||
fn main()
|
||||
{
|
||||
let mut stdin = std::io::stdin();
|
||||
|
||||
// test the mlua crate
|
||||
let lua_state = Lua::new();
|
||||
// set up Lua environment
|
||||
|
||||
lua_state.globals().set("get_rust_value", lua_state.create_function(|_, ()| {
|
||||
Ok(3)
|
||||
}).unwrap()).unwrap();
|
||||
println!("Loading user script...");
|
||||
|
||||
let user_script = std::fs::read_to_string("test.lua").unwrap();
|
||||
lua_state.load(&user_script).exec().unwrap();
|
||||
let script = UserScript::new("test.lua").unwrap();
|
||||
|
||||
let lua_func_test : mlua::Function = lua_state.globals().get("test").unwrap();
|
||||
println!("Calling init()...");
|
||||
|
||||
println!("{}", lua_func_test.call::<_, u32>(123).unwrap());
|
||||
script.init().unwrap();
|
||||
|
||||
// set up signal processing
|
||||
|
||||
println!("Initializing signal processing...");
|
||||
|
||||
let mut sigproc = SignalProcessing::new(config::BLOCK_LEN, config::SAMP_RATE).unwrap();
|
||||
|
||||
|
@ -75,7 +75,10 @@ fn main()
|
|||
let energy_treble = sigproc.get_energy_in_band(4000.0, config::SAMP_RATE/2.0);
|
||||
|
||||
// dump the output
|
||||
println!("Bass: {:8.2} – Mid: {:8.2} – Treble: {:8.2}", energy_bass, energy_mid, energy_treble);
|
||||
println!("Bass: {:11.2} – Mid: {:11.2} – Treble: {:11.2}", energy_bass, energy_mid, energy_treble);
|
||||
|
||||
// call the periodic function in the user script
|
||||
script.periodic().unwrap();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
95
src/userscript.rs
Normal file
95
src/userscript.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
// vim: noet
|
||||
|
||||
/*
|
||||
* Module for the Lua scripting interface of Musiclight.
|
||||
*/
|
||||
|
||||
/* Test code for reference
|
||||
// test the mlua crate
|
||||
let lua_state = Lua::new();
|
||||
|
||||
lua_state.globals().set("get_rust_value", lua_state.create_function(|_, ()| {
|
||||
Ok(3)
|
||||
}).unwrap()).unwrap();
|
||||
|
||||
let user_script = std::fs::read_to_string("test.lua").unwrap();
|
||||
lua_state.load(&user_script).exec().unwrap();
|
||||
|
||||
let lua_func_test : mlua::Function = lua_state.globals().get("test").unwrap();
|
||||
|
||||
println!("{}", lua_func_test.call::<_, u32>(123).unwrap());
|
||||
*/
|
||||
|
||||
use crate::config;
|
||||
|
||||
use mlua::Lua;
|
||||
use mlua::FromLua;
|
||||
use mlua::Error;
|
||||
|
||||
pub struct UserScript
|
||||
{
|
||||
lua_state: Lua,
|
||||
}
|
||||
|
||||
impl UserScript
|
||||
{
|
||||
pub fn new(user_script_path: &str) -> std::result::Result<UserScript, mlua::Error>
|
||||
{
|
||||
let s = UserScript {
|
||||
lua_state: Lua::new(),
|
||||
};
|
||||
|
||||
// load the user script and execute it to make variables and functions available
|
||||
let user_script = std::fs::read_to_string(user_script_path)?;
|
||||
s.lua_state.load(&user_script).exec()?;
|
||||
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
pub fn init(&self) -> std::result::Result<(), mlua::Error>
|
||||
{
|
||||
// find the init functions
|
||||
let lua_init_func: mlua::Function = self.lua_state.globals().get("init")?;
|
||||
|
||||
lua_init_func.call( (config::NUM_STRIPS, config::NUM_LEDS_PER_STRIP) )?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn periodic(&self) -> std::result::Result<(), mlua::Error>
|
||||
{
|
||||
// find the init functions
|
||||
let lua_periodic_func: mlua::Function = self.lua_state.globals().get("periodic")?;
|
||||
|
||||
// call the script's periodic() function, which (hopefully) returns four Tables with color
|
||||
// values
|
||||
let rvals = lua_periodic_func.call::<_, mlua::MultiValue>( () )?;
|
||||
|
||||
// check the number of returned values
|
||||
if rvals.len() != 4 {
|
||||
return Err(Error::RuntimeError("Wrong number of return values from 'periodic'. Expected 4.".to_string()));
|
||||
}
|
||||
|
||||
// convert the Lua Tables to normal vectors
|
||||
let mut colorlists = Vec::<Vec<f32>>::new();
|
||||
|
||||
for rval in rvals {
|
||||
let table = mlua::Table::from_lua(rval, &self.lua_state)?;
|
||||
|
||||
let v = table.sequence_values()
|
||||
.map(|x| x.unwrap())
|
||||
.collect::<Vec<f32>>();
|
||||
|
||||
// check the length of the color array
|
||||
if v.len() != config::NUM_LEDS_TOTAL {
|
||||
return Err(Error::RuntimeError("Number of color values returned from 'periodic' must match number of LEDs given in 'init'.".to_string()));
|
||||
}
|
||||
|
||||
colorlists.push(v);
|
||||
}
|
||||
|
||||
println!("{:?}", colorlists[0][0]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
25
test.lua
Normal file
25
test.lua
Normal file
|
@ -0,0 +1,25 @@
|
|||
function init(nstrip, nmod)
|
||||
print("Initializing with "..nstrip.." strips with "..nmod.." modules each.")
|
||||
|
||||
local nled = nstrip * nmod
|
||||
|
||||
red = {}
|
||||
green = {}
|
||||
blue = {}
|
||||
white = {}
|
||||
|
||||
|
||||
for i = 1,nled do
|
||||
red[i] = 0.8
|
||||
green[i] = 0.1
|
||||
blue[i] = 0.2
|
||||
white[i] = 0.1
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
function periodic()
|
||||
print("Going round and round...")
|
||||
return red, green, blue, white
|
||||
end
|
Loading…
Reference in a new issue