use std::thread::sleep;
use std::time::Duration;
use crossbeam;
use crate::midi;
pub struct Note<'a> {
pub output: &'a mut midir::MidiOutputConnection
}
impl Note<'_> {
pub fn new(&mut self, start_index: usize, mut duration: u64, buffer: &mut std::sync::MutexGuard<std::vec::Vec<midi::time::MidiBuffer>>) {
let (stop_index, stop_timestamp, stop_message) = find_stop_message(start_index, buffer);
crossbeam::scope(|scope| {
scope.spawn(|_| {
let note_duration = stop_timestamp - buffer[start_index].timestamp;
if stop_index <= buffer.len() - 1 && !super::attribute::release_note(buffer[start_index].message.to_vec()) {
println!("{:?} => {:?}", &buffer[start_index].message, &stop_message);
let _ = &self.output.send(&buffer[start_index].message).unwrap_or_else(|_| println!("Error when forwarding message ..."));
if note_duration <= duration {
sleep(Duration::from_micros(note_duration));
let _ = &self.output.send(&stop_message).unwrap_or_else(|_| println!("Error when forwarding message ..."));
if stop_index != buffer.len() - 1 && duration != 0 {
duration = stop_timestamp - buffer[start_index].timestamp;
}
sleep(Duration::from_micros(duration - note_duration));
} else {
sleep(Duration::from_micros(duration));
let _ = &self.output.send(&stop_message).unwrap_or_else(|_| println!("Error when forwarding message ..."));
}
}
});
})
.expect("A child thread panicked");
}
pub fn forward(&mut self, message: &[u8]) {
crossbeam::scope(|scope| {
scope.spawn(|_| {
println!("{:?}", message);
let _ = &self.output.send(message).unwrap_or_else(|_| println!("Error when forwarding message ..."));
});
})
.expect("A child thread panicked");
}
}
fn find_stop_message<'a>(start_index: usize, buffer: &mut std::sync::MutexGuard<std::vec::Vec<midi::time::MidiBuffer>>) -> (usize, u64, Vec<u8>) {
let mut stop_index = start_index + 1;
let start_tone = buffer[start_index].message[1];
let mut stop_id = buffer[stop_index].message[0];
while stop_index < buffer.len() - 1 {
if buffer[stop_index].message[1] == start_tone && buffer[stop_index].message[2] == 0 {
let stop_message: Vec<u8> = [buffer[stop_index].message[0], buffer[stop_index].message[1], buffer[stop_index].message[2]].to_vec();
return (stop_index, buffer[stop_index].timestamp, stop_message)
}
stop_index += 1;
if stop_id == buffer[start_index].message[0] {
stop_id = buffer[stop_index].message[0];
}
}
let default_message: Vec<u8> = [stop_id, start_tone, 0].to_vec();
let default_stop = midi::time::MidiBuffer {timestamp: buffer[start_index + 1].timestamp, message: default_message};
(start_index + 1, default_stop.timestamp, default_stop.message)
}
pub fn trigger(_timestamp: u64, message: &[u8], properties: &str, buffer_length: usize) -> bool {
if super::attribute::release_note(message.to_vec()) {
let props: Vec<&str> = properties.split("|").collect();
match props[0] {
"cycle" => return cycle(props[1].parse::<usize>().unwrap(), buffer_length),
_ => return false
}
}
false
}
fn cycle(sequence: usize, buffer_length: usize) -> bool {
if buffer_length % sequence == 0 {
return true
}
false
}