diff --git a/rust/src/app.rs b/rust/src/app.rs index 0ca031b..7f51a20 100644 --- a/rust/src/app.rs +++ b/rust/src/app.rs @@ -108,7 +108,7 @@ impl App { } break 'signal; } - std::thread::yield_now(); + thread::sleep(Duration::from_millis(500)); } let mut done = false; diff --git a/rust/src/filters/ccmap.rs b/rust/src/filters/ccmap.rs index 2fe4252..5602cdd 100644 --- a/rust/src/filters/ccmap.rs +++ b/rust/src/filters/ccmap.rs @@ -1,9 +1,8 @@ -#[derive(Debug)] -pub struct CCMap { channel : u8, out_cc : Vec } +pub struct CCMap { channel : u8, out_cc : [u8 ; 0xff] } impl CCMap { pub fn new( args : String ) -> CCMap { - let out_cc = vec![ 0 ; 0xff ]; + let out_cc = [ 0u8 ; 0xff ]; let channel = args.split(",").next().unwrap(); let mut ccmap = CCMap { @@ -26,9 +25,8 @@ impl CallbackFn for CCMap { self.out_cc[in_cc] ); } - fn callback(&self, data : &mut CallbackData, buf : &Vec) -> usize { + fn callback(&self, data : &mut CallbackData, buf : &[u8]) -> usize { let exp_state : u8 = 0xb0 + self.channel; - let mut out_buf = [0u8 ; BUFSIZE]; let mut cc : u8 = 0xff; let mut val : u8 = 0xff; @@ -47,9 +45,9 @@ impl CallbackFn for CCMap { } else if val == 0xff { if cc < 0x80 { val = *c; - out_buf[a] = exp_state; a += 1; - out_buf[a] = cc; a += 1; - out_buf[a] = val; a += 1; + data.buffer[a] = exp_state; a += 1; + data.buffer[a] = cc; a += 1; + data.buffer[a] = val; a += 1; } val = 0xff; cc = 0xff; @@ -59,6 +57,6 @@ impl CallbackFn for CCMap { val = 0xff; } } - data.output_device.send_buffer(&out_buf[0..a].to_vec()).unwrap() + data.output_device.send_buffer(&data.buffer[0..a]).unwrap() } } diff --git a/rust/src/filters/channel.rs b/rust/src/filters/channel.rs index 883c74a..30a7adb 100644 --- a/rust/src/filters/channel.rs +++ b/rust/src/filters/channel.rs @@ -1,5 +1,4 @@ -#[derive(Debug)] pub struct Channel { mask : u32 } impl Channel { pub fn new( args : String ) -> Channel { @@ -17,9 +16,8 @@ impl Channel { } } impl CallbackFn for Channel { - fn callback(&self, data : &mut CallbackData, buf : &Vec) -> usize { + fn callback(&self, data : &mut CallbackData, buf : &[u8]) -> usize { let mask = self.mask; - let mut out_buf = [0u8 ; BUFSIZE]; let mut current_mask = 0; if data.output_device.midi_in_exclusive == data.midi_in { @@ -43,10 +41,10 @@ impl CallbackFn for Channel { } if mask & current_mask != 0 { - out_buf[a] = *c; + data.buffer[a] = *c; a += 1; } } - data.output_device.send_buffer(&out_buf[0..a].to_vec()).unwrap() + data.output_device.send_buffer(&data.buffer[0..a]).unwrap() } } diff --git a/rust/src/filters/funnel.rs b/rust/src/filters/funnel.rs index 9828b81..6869b66 100644 --- a/rust/src/filters/funnel.rs +++ b/rust/src/filters/funnel.rs @@ -1,5 +1,4 @@ -#[derive(Debug)] pub struct Funnel { channel : u8 } impl Funnel { pub fn new( args : String ) -> Funnel { @@ -7,9 +6,8 @@ impl Funnel { } } impl CallbackFn for Funnel { - fn callback(&self, data : &mut CallbackData, buf : &Vec) -> usize { + fn callback(&self, data : &mut CallbackData, buf : &[u8]) -> usize { let mask = MASK_ALL; - let mut out_buf = [0u8 ; BUFSIZE]; let mut current_mask = 0; if data.output_device.midi_in_exclusive == data.midi_in { @@ -30,16 +28,16 @@ impl CallbackFn for Funnel { current_mask = MASK_SYSEX; } else if *c >= 0x80 { current_mask = 2 << (*c & 0x0f); - out_buf[a] = *c & 0xf0 | self.channel; + data.buffer[a] = *c & 0xf0 | self.channel; a += 1; continue; } if mask & current_mask != 0 { - out_buf[a] = *c; + data.buffer[a] = *c; a += 1; } } - data.output_device.send_buffer(&out_buf[0..a].to_vec()).unwrap() + data.output_device.send_buffer(&data.buffer[0..a]).unwrap() } } diff --git a/rust/src/filters/mod.rs b/rust/src/filters/mod.rs index 89eea8c..b622449 100644 --- a/rust/src/filters/mod.rs +++ b/rust/src/filters/mod.rs @@ -19,7 +19,7 @@ fn parse_hex(arg : &str) -> u8 { #[derive(Debug)] pub struct Void { } impl Void { pub fn new( _args : String ) -> Void { Void { } } } -impl CallbackFn for Void { fn callback(&self, _data : &mut CallbackData, _buf : &Vec) -> usize { 0 } } +impl CallbackFn for Void { fn callback(&self, _data : &mut CallbackData, _buf : &[u8]) -> usize { 0 } } include!("channel.rs"); include!("funnel.rs"); @@ -27,7 +27,6 @@ include!("ccmap.rs"); include!("status.rs"); #[enum_dispatch] -#[derive(Debug)] pub enum Callback { Void, Channel, @@ -38,7 +37,7 @@ pub enum Callback { #[enum_dispatch(Callback)] pub trait CallbackFn { - fn callback(&self, _data : &mut CallbackData, _buf : &Vec) -> usize; + fn callback(&self, _data : &mut CallbackData, _buf : &[u8]) -> usize; fn add_args( &mut self, _args : String ) {} } @@ -53,3 +52,8 @@ impl Callback { } } } +impl std::fmt::Debug for Callback { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "Callback {{ }}") + } +} diff --git a/rust/src/filters/status.rs b/rust/src/filters/status.rs index a9782a1..536b97c 100644 --- a/rust/src/filters/status.rs +++ b/rust/src/filters/status.rs @@ -1,10 +1,9 @@ use std::convert::TryInto; -#[derive(Debug)] -pub struct Status { out_status : Vec } +pub struct Status { out_status : [u8 ; 0x80] } impl Status { pub fn new( args : String ) -> Status { - let mut out_status = vec![ 0 ; 0x80 ]; + let mut out_status = [ 0 ; 0x80 ]; for arg in args.split(",") { let status = parse_hex(arg); let i : usize = ((0x80 | status) - 0x80).try_into().unwrap(); @@ -14,9 +13,7 @@ impl Status { } } impl CallbackFn for Status { - fn callback(&self, data : &mut CallbackData, buf : &Vec) -> usize { - let mut out_buf = [0u8 ; BUFSIZE]; - + fn callback(&self, data : &mut CallbackData, buf : &[u8]) -> usize { let mut a = 0; let out_status = &self.out_status; @@ -24,10 +21,10 @@ impl CallbackFn for Status { let cur_state = data.output_device.scan_status(*c); let i : usize = ((0x80 | cur_state) - 0x80).try_into().unwrap(); if out_status[i] == cur_state { - out_buf[ a ] = *c; + data.buffer[ a ] = *c; a += 1; } } - data.output_device.send_buffer(&out_buf[0..a].to_vec()).unwrap() + data.output_device.send_buffer(&data.buffer[0..a]).unwrap() } } diff --git a/rust/src/output.rs b/rust/src/output.rs index dadbffc..41b61f9 100644 --- a/rust/src/output.rs +++ b/rust/src/output.rs @@ -45,20 +45,23 @@ impl OutputDevice { }, } } - pub fn send_buffer(&mut self, buf : &Vec ) -> Result { + pub fn send_buffer(&mut self, buf : &[u8] ) -> Result { + if buf.len() == 0 { + return Ok(0) + } let midi = match &self.midi { Some(mutex) => match mutex.lock() { Ok(m) => m, Err(_) => return Err(format!("Could not lock {}", self.port_name)), }, None => { - println!("Device not connected {}", self.port_name); + //println!("Device not connected {}", self.port_name); return Ok(0) }, }; match midi.io().write(buf) { Ok(n) => { - self.handle_write(buf.to_vec()); + self.handle_write(buf); let mut status : u8 = self.status; for c in buf.iter() { if *c >= 0x80 { @@ -71,7 +74,7 @@ impl OutputDevice { Err(_) => Err(format!("Error writing to {}", self.port_name)), } } - fn handle_write(&self, buf : Vec) { + fn handle_write(&self, buf : &[u8]) { print!("O"); for x in buf.iter(){ print!(" 0x{:02x}", x); } println!(" {}", self.port_name); diff --git a/rust/src/thru.rs b/rust/src/thru.rs index 30742dc..562b7f6 100644 --- a/rust/src/thru.rs +++ b/rust/src/thru.rs @@ -51,12 +51,12 @@ impl ReadData { self.outs.push( WriteData::new(&out, func, args) ); } - fn handle_read(&mut self, buf : Vec) { + fn handle_read(&mut self, buf : &[u8]) { print!("I"); for x in buf.iter(){ print!(" 0x{:02x}", x); } println!(" {}", self.port_name); for w in self.outs.iter_mut() { - w.call(&buf); + w.call(buf); } } } @@ -73,21 +73,49 @@ impl fmt::Debug for ReadThread { } impl ReadThread { fn read_loop( flags : &Arc, arc : &Arc>, midi : &Rawmidi ) { + /* + // calculate BPM + let mut clock = std::time::Instant::now(); + let mut clock1; + const BPM_SIZE : usize = 32; + let mut bpms = vec![ 0.0f64 ; BPM_SIZE]; + let mut bpm_offset : usize = 0; + */ + let mut buf = [0u8; BUFSIZE]; 'read: loop { use alsa::PollDescriptors; - let mut buf : Vec = vec![0; BUFSIZE]; while ! flags.run.load(Ordering::Relaxed) { if flags.hup.swap(false, Ordering::Relaxed) { break 'read; } thread::sleep(Duration::from_millis(500)); } - thread::yield_now(); + //thread::yield_now(); if flags.int.load(Ordering::Relaxed) { break 'read; } let res = alsa::poll::poll(&mut midi.get().unwrap(), 500).unwrap(); + //clock1 = std::time::Instant::now(); if res == 0 { continue; } + match midi.io().read(&mut buf) { Ok(n) => { - arc.write().unwrap().handle_read( buf[0..n].to_vec() ); + /* + // calculate BPM + for c in &buf[0..n] { + if *c == 0xf8 { + let bpm = 2_500_000.0f64 / (clock1.duration_since(clock).as_micros() as f64); + bpms[ bpm_offset ] = bpm; + bpm_offset = (bpm_offset + 1) % BPM_SIZE; + let mut sum : f64 = 0.0; + for b in &bpms { + sum += b; + } + sum /= BPM_SIZE as f64; + println!("Tempo = {:?} BPM", sum); + clock = clock1; + break; + } + } + */ + arc.write().unwrap().handle_read( &buf[0..n] ); }, Err(_) => { println!("Error reading"); diff --git a/rust/src/write.rs b/rust/src/write.rs index b86a2e6..97ba9e3 100644 --- a/rust/src/write.rs +++ b/rust/src/write.rs @@ -3,9 +3,11 @@ use std::fmt; use crate::filters::CallbackFn; use crate::output::OutputDevice; use crate::filters; +use crate::thru::BUFSIZE; pub struct CallbackData<'a> { pub output_device : &'a mut OutputDevice, + pub buffer : &'a mut [u8], pub midi_in : String, } @@ -15,6 +17,7 @@ pub struct WriteData { args: String, pub midi_in : String, pub callback : filters::Callback, + pub buffer : [u8 ; BUFSIZE], } impl fmt::Debug for WriteData { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -30,15 +33,23 @@ impl WriteData { func_name: func.clone(), args: args.clone(), midi_in: "".to_string(), + buffer: [ 0u8 ; BUFSIZE ], callback: filters::Callback::new( func, args.clone() ), } } pub fn add_args(&mut self, args : String) { self.callback.add_args(args); } - pub fn call(&mut self, buf : &Vec) { + pub fn call(&mut self, buf : &[u8]) { + let output_device = &mut match self.output_device.write() { + Ok(dev) => dev, + Err(_) => { + return; + }, + }; let mut data = CallbackData { - output_device: &mut self.output_device.write().unwrap(), + output_device: output_device, + buffer: &mut self.buffer, midi_in: self.midi_in.to_string(), }; self.callback.callback(&mut data, buf);