This commit is contained in:
Jade Rowland 2023-09-09 01:20:08 -04:00
parent 133a1d2e8f
commit e75ac7b3c0
6 changed files with 84 additions and 12 deletions

View File

@ -0,0 +1,11 @@
import { listen } from '@tauri-apps/api/event';
import { logger } from '../core/logger.mjs';
// listen for log events from the Tauri backend and log in the UI
await listen('log-event', (e) => {
if (e.payload == null) {
return;
}
const { message, message_type } = e.payload;
logger(message, message_type);
});

View File

@ -0,0 +1,20 @@
use std::sync::Arc;
use tauri::Window;
#[derive(Clone, serde::Serialize)]
pub struct LoggerPayload {
pub message: String,
pub message_type: String,
}
#[derive(Clone)]
pub struct Logger {
pub window: Arc<Window>,
}
impl Logger {
pub fn log(&self, message: String, message_type: String) {
println!("{}", message);
let _ = self.window.emit("log-event", LoggerPayload { message, message_type });
}
}

View File

@ -3,9 +3,21 @@
mod midibridge;
mod oscbridge;
mod loggerbridge;
use std::sync::Arc;
use std::thread::sleep;
use std::time::Duration;
use loggerbridge::Logger;
use tauri::Manager;
use tokio::sync::mpsc;
use tokio::sync::Mutex;
// the payload type must implement `Serialize` and `Clone`.
#[derive(Clone, serde::Serialize)]
struct Payload {
message: String,
message_type: String,
}
fn main() {
let (async_input_transmitter_midi, async_input_receiver_midi) = mpsc::channel(1);
let (async_output_transmitter_midi, async_output_receiver_midi) = mpsc::channel(1);
@ -20,9 +32,16 @@ fn main() {
inner: Mutex::new(async_input_transmitter_osc),
})
.invoke_handler(tauri::generate_handler![midibridge::sendmidi, oscbridge::sendosc])
.setup(|_app| {
midibridge::init(async_input_receiver_midi, async_output_receiver_midi, async_output_transmitter_midi);
oscbridge::init(async_input_receiver_osc, async_output_receiver_osc, async_output_transmitter_osc);
.setup(|app| {
let window = Arc::new(app.get_window("main").unwrap());
let logger = Logger { window };
midibridge::init(
logger.clone(),
async_input_receiver_midi,
async_output_receiver_midi,
async_output_transmitter_midi
);
oscbridge::init(logger, async_input_receiver_osc, async_output_receiver_osc, async_output_transmitter_osc);
Ok(())
})
.run(tauri::generate_context!())

View File

@ -2,10 +2,13 @@ use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
use midir::MidiOutput;
use tokio::sync::{ mpsc, Mutex };
use tokio::time::Instant;
use serde::Deserialize;
use std::thread::sleep;
use crate::loggerbridge::Logger;
pub struct MidiMessage {
pub message: Vec<u8>,
pub instant: Instant,
@ -18,6 +21,7 @@ pub struct AsyncInputTransmit {
}
pub fn init(
logger: Logger,
async_input_receiver: mpsc::Receiver<Vec<MidiMessage>>,
mut async_output_receiver: mpsc::Receiver<Vec<MidiMessage>>,
async_output_transmitter: mpsc::Sender<Vec<MidiMessage>>
@ -50,10 +54,13 @@ pub fn init(
let mut port_names = Vec::new();
//TODO: Send these print messages to the UI logger instead of the rust console so the user can see them
if out_ports.len() == 0 {
println!(" No MIDI devices found. Connect a device or enable IAC Driver.");
logger.log(" No MIDI devices found. Connect a device or enable IAC Driver.".to_string(), "".to_string());
// logger(window, " No MIDI devices found. Connect a device or enable IAC Driver.".to_string(), None);
return;
}
println!("Found {} midi devices!", out_ports.len());
// give the frontend couple seconds to load on start, or the log messages will get lost
sleep(Duration::from_secs(3));
logger.log(format!("Found {} midi devices!", out_ports.len()), "".to_string());
// the user could reference any port at anytime during runtime,
// so let's go ahead and open them all (same behavior as web app)
@ -63,7 +70,7 @@ pub fn init(
let ports = midiout.ports();
let port = ports.get(i).unwrap();
let port_name = midiout.port_name(port).unwrap();
println!("{}", port_name);
logger.log(port_name.clone(), "".to_string());
let out_con = midiout.connect(port, &port_name).unwrap();
port_names.insert(i, port_name.clone());
output_connections.insert(port_name, out_con);
@ -96,10 +103,10 @@ pub fn init(
if out_con.is_some() {
// process the message
if let Err(err) = (&mut out_con.unwrap()).send(&message.message) {
println!("Midi message send error: {}", err);
logger.log(format!("Midi message send error: {}", err), "warning".to_string());
}
} else {
println!("failed to find midi device: {}", message.requestedport);
logger.log(format!("failed to find midi device: {}", message.requestedport), "warning".to_string());
}
return false;
});

View File

@ -1,5 +1,6 @@
use rosc::{ encoder, OscTime };
use rosc::{ OscMessage, OscPacket, OscType, OscBundle };
use std::net::UdpSocket;
use std::time::Duration;
@ -7,6 +8,8 @@ use std::sync::Arc;
use tokio::sync::{ mpsc, Mutex };
use serde::Deserialize;
use std::thread::sleep;
use crate::loggerbridge::Logger;
pub struct OscMsg {
pub msg_buf: Vec<u8>,
pub timestamp: u64,
@ -22,6 +25,7 @@ const NANOS_PER_SECOND: f64 = 1.0e9;
const SECONDS_PER_NANO: f64 = 1.0 / NANOS_PER_SECOND;
pub fn init(
logger: Logger,
async_input_receiver: mpsc::Receiver<Vec<OscMsg>>,
mut async_output_receiver: mpsc::Receiver<Vec<OscMsg>>,
async_output_transmitter: mpsc::Sender<Vec<OscMsg>>
@ -64,7 +68,10 @@ pub fn init(
message_queue.retain(|message| {
let result = sock.send(&message.msg_buf);
if result.is_err() {
println!("OSC Message failed to send, the server might no longer be available");
logger.log(
format!("OSC Message failed to send, the server might no longer be available"),
"warning".to_string()
);
}
return false;
});

View File

@ -37,14 +37,22 @@ const modules = [
import('@strudel.cycles/core'),
import('@strudel.cycles/tonal'),
import('@strudel.cycles/mini'),
isTauri() ? import('@strudel/desktopbridge/midibridge.mjs') : import('@strudel.cycles/midi'),
import('@strudel.cycles/xen'),
import('@strudel.cycles/webaudio'),
isTauri() ? import('@strudel/desktopbridge/oscbridge.mjs') : import('@strudel.cycles/osc'),
import('@strudel.cycles/serial'),
import('@strudel.cycles/soundfonts'),
import('@strudel.cycles/csound'),
];
if (isTauri()) {
modules.concat([
import('@strudel/desktopbridge/loggerbridge.mjs'),
import('@strudel/desktopbridge/midibridge.mjs'),
import('@strudel/desktopbridge/oscbridge.mjs'),
]);
} else {
modules.concat([import('@strudel.cycles/midi'), import('@strudel.cycles/osc')]);
}
const modulesLoading = evalScope(
controls, // sadly, this cannot be exported from core direclty