/looper/metronome/position in audio_engine
This commit is contained in:
@@ -10,31 +10,29 @@ impl OscController {
|
||||
Self { sender }
|
||||
}
|
||||
|
||||
pub fn track_state_changed(
|
||||
&self,
|
||||
column: usize,
|
||||
row: usize,
|
||||
state: TrackState,
|
||||
) -> Result<()> {
|
||||
let message = osc::Message::TrackStateChanged { column, row, state: state.into() };
|
||||
pub fn track_state_changed(&self, column: usize, row: usize, state: TrackState) -> Result<()> {
|
||||
let message = osc::Message::TrackStateChanged {
|
||||
column,
|
||||
row,
|
||||
state: state.into(),
|
||||
};
|
||||
match self.sender.try_send(message) {
|
||||
Ok(true) => Ok(()),
|
||||
Ok(false) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel full
|
||||
Err(_) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel closed
|
||||
Err(_) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel closed
|
||||
}
|
||||
}
|
||||
|
||||
pub fn track_volume_changed(
|
||||
&self,
|
||||
column: usize,
|
||||
row: usize,
|
||||
volume: f32,
|
||||
) -> Result<()> {
|
||||
let message = osc::Message::TrackVolumeChanged { column, row, volume };
|
||||
pub fn track_volume_changed(&self, column: usize, row: usize, volume: f32) -> Result<()> {
|
||||
let message = osc::Message::TrackVolumeChanged {
|
||||
column,
|
||||
row,
|
||||
volume,
|
||||
};
|
||||
match self.sender.try_send(message) {
|
||||
Ok(true) => Ok(()),
|
||||
Ok(false) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel full
|
||||
Err(_) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel closed
|
||||
Err(_) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel closed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +41,7 @@ impl OscController {
|
||||
match self.sender.try_send(message) {
|
||||
Ok(true) => Ok(()),
|
||||
Ok(false) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel full
|
||||
Err(_) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel closed
|
||||
Err(_) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel closed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +50,16 @@ impl OscController {
|
||||
match self.sender.try_send(message) {
|
||||
Ok(true) => Ok(()),
|
||||
Ok(false) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel full
|
||||
Err(_) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel closed
|
||||
Err(_) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel closed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metronome_position_changed(&self, position: f32) -> Result<()> {
|
||||
let message = osc::Message::MetronomePosition { position };
|
||||
match self.sender.try_send(message) {
|
||||
Ok(true) => Ok(()),
|
||||
Ok(false) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel full
|
||||
Err(_) => Err(LooperError::Osc(std::panic::Location::caller())), // Channel closed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,4 @@ mod server;
|
||||
|
||||
// Re-export public interface - same as before
|
||||
pub use controller::OscController;
|
||||
pub use server::Osc;
|
||||
pub use server::Osc;
|
||||
|
||||
@@ -20,4 +20,4 @@ pub(crate) async fn create_listener(socket_path: &str) -> Result<PlatformListene
|
||||
{
|
||||
windows::create_listener(socket_path).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ pub(crate) struct PlatformListener {
|
||||
|
||||
impl PlatformListener {
|
||||
pub async fn accept(&mut self) -> Result<PlatformStream> {
|
||||
let (stream, _) = self.listener.accept().await
|
||||
let (stream, _) = self
|
||||
.listener
|
||||
.accept()
|
||||
.await
|
||||
.map_err(|_| LooperError::JackConnection(std::panic::Location::caller()))?;
|
||||
Ok(stream)
|
||||
}
|
||||
@@ -18,9 +21,9 @@ impl PlatformListener {
|
||||
pub(crate) async fn create_listener(socket_path: &str) -> Result<PlatformListener> {
|
||||
// Remove existing socket file if it exists
|
||||
let _ = std::fs::remove_file(socket_path);
|
||||
|
||||
|
||||
let listener = UnixListener::bind(socket_path)
|
||||
.map_err(|_| LooperError::JackConnection(std::panic::Location::caller()))?;
|
||||
|
||||
|
||||
Ok(PlatformListener { listener })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,13 @@ impl PlatformListener {
|
||||
if self.current_server.is_none() {
|
||||
self.current_server = Some(create_pipe_server(&self.pipe_name)?);
|
||||
}
|
||||
|
||||
|
||||
let server = self.current_server.take().unwrap();
|
||||
server.connect().await
|
||||
server
|
||||
.connect()
|
||||
.await
|
||||
.map_err(|_| LooperError::JackConnection(std::panic::Location::caller()))?;
|
||||
|
||||
|
||||
Ok(server)
|
||||
}
|
||||
}
|
||||
@@ -30,7 +32,7 @@ pub(crate) async fn create_listener(pipe_name: &str) -> Result<PlatformListener>
|
||||
} else {
|
||||
format!(r"\\.\pipe\{}", pipe_name)
|
||||
};
|
||||
|
||||
|
||||
Ok(PlatformListener {
|
||||
pipe_name: pipe_path,
|
||||
current_server: None,
|
||||
@@ -42,4 +44,4 @@ fn create_pipe_server(pipe_name: &str) -> Result<NamedPipeServer> {
|
||||
.first_pipe_instance(false)
|
||||
.create(pipe_name)
|
||||
.map_err(|_| LooperError::JackConnection(std::panic::Location::caller()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ impl Osc {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Accept new client connections
|
||||
connection = self.listener.accept() => {
|
||||
if let Ok(stream) = connection {
|
||||
@@ -63,17 +63,20 @@ impl Osc {
|
||||
fn spawn_client_task(&self, stream: osc_server::platform::PlatformStream) {
|
||||
let mut receiver = self.broadcaster.subscribe();
|
||||
let state_dump = self.shadow_state.create_state_dump();
|
||||
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut framed = tokio_util::codec::Framed::new(stream, tokio_util::codec::LengthDelimitedCodec::new());
|
||||
|
||||
let mut framed = tokio_util::codec::Framed::new(
|
||||
stream,
|
||||
tokio_util::codec::LengthDelimitedCodec::new(),
|
||||
);
|
||||
|
||||
// Send current state dump immediately
|
||||
for msg in state_dump {
|
||||
if let Err(_) = Self::send_osc_message(&mut framed, msg).await {
|
||||
return; // Client disconnected during state dump
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Forward broadcast messages until connection dies
|
||||
while let Ok(msg) = receiver.recv().await {
|
||||
if let Err(_) = Self::send_osc_message(&mut framed, msg).await {
|
||||
@@ -84,11 +87,14 @@ impl Osc {
|
||||
}
|
||||
|
||||
async fn send_osc_message(
|
||||
framed: &mut tokio_util::codec::Framed<osc_server::platform::PlatformStream, tokio_util::codec::LengthDelimitedCodec>,
|
||||
framed: &mut tokio_util::codec::Framed<
|
||||
osc_server::platform::PlatformStream,
|
||||
tokio_util::codec::LengthDelimitedCodec,
|
||||
>,
|
||||
message: osc::Message,
|
||||
) -> Result<()> {
|
||||
let osc_packet = Self::message_to_osc_packet(message)?;
|
||||
|
||||
let osc_packet = message.to_osc_packet();
|
||||
|
||||
let osc_bytes = rosc::encoder::encode(&osc_packet)
|
||||
.map_err(|_| crate::LooperError::StateSave(std::panic::Location::caller()))?;
|
||||
|
||||
@@ -99,41 +105,4 @@ impl Osc {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn message_to_osc_packet(message: osc::Message) -> Result<rosc::OscPacket> {
|
||||
match message {
|
||||
osc::Message::TrackStateChanged { column, row, state } => {
|
||||
let address = format!("/looper/cell/{}/{}/state", column + 1, row + 1); // 1-based indexing
|
||||
|
||||
Ok(rosc::OscPacket::Message(rosc::OscMessage {
|
||||
addr: address,
|
||||
args: vec![rosc::OscType::String(state.to_string())],
|
||||
}))
|
||||
}
|
||||
osc::Message::TrackVolumeChanged { column, row, volume } => {
|
||||
let address = format!("/looper/cell/{}/{}/volume", column + 1, row + 1); // 1-based indexing
|
||||
|
||||
Ok(rosc::OscPacket::Message(rosc::OscMessage {
|
||||
addr: address,
|
||||
args: vec![rosc::OscType::Float(volume)],
|
||||
}))
|
||||
}
|
||||
osc::Message::SelectedColumnChanged { column } => {
|
||||
let address = "/looper/selected/column".to_string();
|
||||
|
||||
Ok(rosc::OscPacket::Message(rosc::OscMessage {
|
||||
addr: address,
|
||||
args: vec![rosc::OscType::Int((column + 1) as i32)], // 1-based indexing
|
||||
}))
|
||||
}
|
||||
osc::Message::SelectedRowChanged { row } => {
|
||||
let address = "/looper/selected/row".to_string();
|
||||
|
||||
Ok(rosc::OscPacket::Message(rosc::OscMessage {
|
||||
addr: address,
|
||||
args: vec![rosc::OscType::Int((row + 1) as i32)], // 1-based indexing
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user