Fix and display metronome
This commit is contained in:
@@ -6,5 +6,6 @@ edition = "2021"
|
||||
[dependencies]
|
||||
strum = { version = "0.23", features = ["derive"] }
|
||||
|
||||
log.workspace = true
|
||||
rosc.workspace = true
|
||||
thiserror.workspace = true
|
||||
@@ -10,8 +10,13 @@ pub trait AddressParseResult<T> {
|
||||
fn address_part_result(self, context: &'static str) -> Result<T>;
|
||||
}
|
||||
|
||||
impl <T> AddressParseResult <T> for std::result::Result<T, std::num::ParseIntError> {
|
||||
impl<T> AddressParseResult<T> for std::result::Result<T, std::num::ParseIntError> {
|
||||
fn address_part_result(self, context: &'static str) -> Result<T> {
|
||||
self.map_err(|e| Error::AddressParseError(format!("failed to parse number in address part {}: {}", context, e)))
|
||||
self.map_err(|e| {
|
||||
Error::AddressParseError(format!(
|
||||
"failed to parse number in address part {}: {}",
|
||||
context, e
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,4 +8,4 @@ pub use error::Result;
|
||||
pub use message::Message;
|
||||
pub use state::State;
|
||||
pub use state::Track;
|
||||
pub use state::TrackState;
|
||||
pub use state::TrackState;
|
||||
|
||||
@@ -77,6 +77,7 @@ impl Message {
|
||||
|
||||
if let Some(rosc::OscType::String(state_str)) = args.first() {
|
||||
let state = state_str.parse::<TrackState>().unwrap_or(TrackState::Empty);
|
||||
log::trace!("TrackStateChanged: column={column}, row={row}, state={state}");
|
||||
return Ok(Some(Message::TrackStateChanged { column, row, state }));
|
||||
}
|
||||
} else if addr.starts_with("/looper/cell/") && addr.ends_with("/volume") {
|
||||
@@ -90,26 +91,30 @@ impl Message {
|
||||
let row: usize = parts[4].parse::<usize>().address_part_result("row")? - 1; // Convert to 0-based
|
||||
|
||||
if let Some(rosc::OscType::Float(volume)) = args.first() {
|
||||
return Ok(Some(Message::TrackVolumeChanged {
|
||||
column,
|
||||
row,
|
||||
volume: *volume
|
||||
log::trace!("TrackVolumeChanged: column={column}, row={row}, volume={volume}");
|
||||
return Ok(Some(Message::TrackVolumeChanged {
|
||||
column,
|
||||
row,
|
||||
volume: *volume,
|
||||
}));
|
||||
}
|
||||
} else if addr == "/looper/selected/column" {
|
||||
if let Some(rosc::OscType::Int(column_1based)) = args.first() {
|
||||
log::trace!("SelectedColumnChanged: column={column_1based}");
|
||||
let column = (*column_1based as usize).saturating_sub(1); // Convert to 0-based
|
||||
return Ok(Some(Message::SelectedColumnChanged { column }));
|
||||
}
|
||||
} else if addr == "/looper/selected/row" {
|
||||
if let Some(rosc::OscType::Int(row_1based)) = args.first() {
|
||||
log::trace!("SelectedRowChanged: row={row_1based}");
|
||||
let row = (*row_1based as usize).saturating_sub(1); // Convert to 0-based
|
||||
return Ok(Some(Message::SelectedRowChanged { row }));
|
||||
}
|
||||
} else if addr == "/looper/metronome/position" {
|
||||
if let Some(rosc::OscType::Float(position)) = args.first() {
|
||||
return Ok(Some(Message::MetronomePosition {
|
||||
position: *position
|
||||
log::trace!("MetronomePosition: position={position}");
|
||||
return Ok(Some(Message::MetronomePosition {
|
||||
position: *position,
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -121,15 +126,19 @@ impl Message {
|
||||
match self {
|
||||
Message::TrackStateChanged { column, row, state } => {
|
||||
let address = format!("/looper/cell/{}/{}/state", column + 1, row + 1); // 1-based indexing
|
||||
|
||||
|
||||
rosc::OscPacket::Message(rosc::OscMessage {
|
||||
addr: address,
|
||||
args: vec![rosc::OscType::String(state.to_string())],
|
||||
})
|
||||
}
|
||||
Message::TrackVolumeChanged { column, row, volume } => {
|
||||
Message::TrackVolumeChanged {
|
||||
column,
|
||||
row,
|
||||
volume,
|
||||
} => {
|
||||
let address = format!("/looper/cell/{}/{}/volume", column + 1, row + 1); // 1-based indexing
|
||||
|
||||
|
||||
rosc::OscPacket::Message(rosc::OscMessage {
|
||||
addr: address,
|
||||
args: vec![rosc::OscType::Float(volume)],
|
||||
@@ -137,7 +146,7 @@ impl Message {
|
||||
}
|
||||
Message::SelectedColumnChanged { column } => {
|
||||
let address = "/looper/selected/column".to_string();
|
||||
|
||||
|
||||
rosc::OscPacket::Message(rosc::OscMessage {
|
||||
addr: address,
|
||||
args: vec![rosc::OscType::Int((column + 1) as i32)], // 1-based indexing
|
||||
@@ -145,7 +154,7 @@ impl Message {
|
||||
}
|
||||
Message::SelectedRowChanged { row } => {
|
||||
let address = "/looper/selected/row".to_string();
|
||||
|
||||
|
||||
rosc::OscPacket::Message(rosc::OscMessage {
|
||||
addr: address,
|
||||
args: vec![rosc::OscType::Int((row + 1) as i32)], // 1-based indexing
|
||||
@@ -153,7 +162,7 @@ impl Message {
|
||||
}
|
||||
Message::MetronomePosition { position } => {
|
||||
let address = "/looper/metronome/position".to_string();
|
||||
|
||||
|
||||
rosc::OscPacket::Message(rosc::OscMessage {
|
||||
addr: address,
|
||||
args: vec![rosc::OscType::Float(position)],
|
||||
@@ -161,4 +170,4 @@ impl Message {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ pub struct Track {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct State {
|
||||
pub selected_column: usize, // 0-based (converted to 1-based for OSC)
|
||||
pub selected_row: usize, // 0-based (converted to 1-based for OSC)
|
||||
pub selected_column: usize, // 0-based (converted to 1-based for OSC)
|
||||
pub selected_row: usize, // 0-based (converted to 1-based for OSC)
|
||||
pub cells: Vec<Vec<Track>>,
|
||||
pub columns: usize,
|
||||
pub rows: usize,
|
||||
@@ -28,9 +28,17 @@ pub struct State {
|
||||
impl State {
|
||||
pub fn new(columns: usize, rows: usize) -> Self {
|
||||
let cells = (0..columns)
|
||||
.map(|_| vec![Track { state: TrackState::Empty, volume: 1.0 }; rows])
|
||||
.map(|_| {
|
||||
vec![
|
||||
Track {
|
||||
state: TrackState::Empty,
|
||||
volume: 1.0
|
||||
};
|
||||
rows
|
||||
]
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
||||
Self {
|
||||
selected_column: 0,
|
||||
selected_row: 0,
|
||||
@@ -49,7 +57,11 @@ impl State {
|
||||
self.cells[*column][*row].state = state.clone();
|
||||
}
|
||||
}
|
||||
Message::TrackVolumeChanged { column, row, volume } => {
|
||||
Message::TrackVolumeChanged {
|
||||
column,
|
||||
row,
|
||||
volume,
|
||||
} => {
|
||||
if *column < self.columns && *row < self.rows {
|
||||
self.cells[*column][*row].volume = *volume;
|
||||
}
|
||||
@@ -128,4 +140,4 @@ impl State {
|
||||
self.metronome_position = position;
|
||||
self.metronome_timestamp = std::time::Instant::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user