From 04bf5cdbb65e88c4a34d79cf3c1d9d9b202a0bbd Mon Sep 17 00:00:00 2001 From: Kaydax Date: Thu, 13 Mar 2025 18:10:59 -0400 Subject: [PATCH 1/2] Add xsynth-interface module --- Cargo.lock | 190 +++++++++++++++++++++++----- Cargo.toml | 2 +- README.md | 13 +- interface/Cargo.toml | 19 +++ interface/README.md | 3 + interface/src/main.rs | 93 ++++++++++++++ interface/src/parsers.rs | 81 ++++++++++++ interface/src/parsers/settings.rs | 56 ++++++++ interface/src/parsers/soundfonts.rs | 74 +++++++++++ kdmapi/Cargo.toml | 2 +- kdmapi/README.md | 2 +- kdmapi/src/parsers.rs | 2 +- 12 files changed, 498 insertions(+), 39 deletions(-) create mode 100644 interface/Cargo.toml create mode 100644 interface/README.md create mode 100644 interface/src/main.rs create mode 100644 interface/src/parsers.rs create mode 100644 interface/src/parsers/settings.rs create mode 100644 interface/src/parsers/soundfonts.rs diff --git a/Cargo.lock b/Cargo.lock index f872b21e..238a65a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,6 +163,12 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "bumpalo" version = "3.12.1" @@ -347,11 +353,21 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "coreaudio-rs" @@ -373,6 +389,27 @@ dependencies = [ "bindgen", ] +[[package]] +name = "coremidi" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964eb3e10ea8b0d29c797086aab3ca730f75e06dced0cb980642fd274a5cca30" +dependencies = [ + "block", + "core-foundation", + "core-foundation-sys", + "coremidi-sys", +] + +[[package]] +name = "coremidi-sys" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709d142e542467e028d5dc5f0374392339ab7dead0c48c129504de2ccd667e1b" +dependencies = [ + "core-foundation-sys", +] + [[package]] name = "cpal" version = "0.15.3" @@ -393,7 +430,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows", + "windows 0.54.0", ] [[package]] @@ -496,23 +533,23 @@ checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" [[package]] name = "directories" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -765,7 +802,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.63", "walkdir", "windows-sys 0.45.0", ] @@ -834,7 +871,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -932,7 +969,7 @@ dependencies = [ "midi-toolkit-rs-derive", "num-traits", "rayon", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -949,6 +986,23 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "midir" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e77a0c42a20fdcb979064b996b7ba8a0030a866832d6ea5ab689a0688ef3a9" +dependencies = [ + "alsa", + "bitflags 1.3.2", + "coremidi", + "js-sys", + "libc", + "parking_lot", + "wasm-bindgen", + "web-sys", + "windows 0.56.0", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -978,7 +1032,7 @@ dependencies = [ "log", "ndk-sys", "num_enum", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -1055,7 +1109,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -1094,7 +1148,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -1384,13 +1438,13 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 2.0.12", ] [[package]] @@ -1424,7 +1478,7 @@ checksum = "ccd8d4222c7fe394fb5ae81c08515107316596c8d4594f1a0d636919350c7eff" dependencies = [ "regex", "regex-bnf-macro", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -1535,7 +1589,7 @@ checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -1751,9 +1805,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -1794,7 +1848,16 @@ version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.63", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] @@ -1805,7 +1868,18 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", ] [[package]] @@ -1915,7 +1989,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -1949,7 +2023,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2016,7 +2090,17 @@ version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ - "windows-core", + "windows-core 0.54.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +dependencies = [ + "windows-core 0.56.0", "windows-targets 0.52.6", ] @@ -2030,6 +2114,40 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -2290,11 +2408,25 @@ dependencies = [ "simdeez", "spin_sleep", "symphonia", - "thiserror", + "thiserror 1.0.63", "to_vec", "xsynth-soundfonts", ] +[[package]] +name = "xsynth-interface" +version = "0.3.2" +dependencies = [ + "cfg-if", + "directories", + "hotwatch", + "midir", + "serde", + "serde_json", + "xsynth-core", + "xsynth-realtime", +] + [[package]] name = "xsynth-kdmapi" version = "0.3.2" @@ -2340,7 +2472,7 @@ dependencies = [ "midi-toolkit-rs", "rayon", "spin_sleep", - "thiserror", + "thiserror 1.0.63", "xsynth-core", ] @@ -2355,5 +2487,5 @@ dependencies = [ "rubato", "simdeez", "soundfont", - "thiserror", + "thiserror 1.0.63", ] diff --git a/Cargo.toml b/Cargo.toml index 4565f675..874d6dd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["core", "clib", "soundfonts", "realtime", "render", "kdmapi"] +members = ["core", "clib", "soundfonts", "realtime", "render", "kdmapi", "interface"] [workspace.package] version = "0.3.2" diff --git a/README.md b/README.md index 1476dbf1..27477108 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,13 @@ ## Modules -- [`core`](https://github.com/BlackMIDIDevs/xsynth/tree/master/core): Handles the core audio rendering functionality. -- [`clib`](https://github.com/BlackMIDIDevs/xsynth/tree/master/clib): C/C++ bindings for XSynth. -- [`soundfonts`](https://github.com/BlackMIDIDevs/xsynth/tree/master/soundfonts): A module to parse soundfonts to be used in XSynth. -- [`realtime`](https://github.com/BlackMIDIDevs/xsynth/tree/master/realtime): The real-time rendering module within XSynth. -- [`render`](https://github.com/BlackMIDIDevs/xsynth/tree/master/render): A command line utility for rendering MIDIs to audio using XSynth. -- [`kdmapi`](https://github.com/BlackMIDIDevs/xsynth/tree/master/render): A cdylib wrapper around XSynth to act as a drop in replacement for OmniMIDI/KDMAPI. +- [`core`](/core): Handles the core audio rendering functionality. +- [`clib`](/clib): C/C++ bindings for XSynth. +- [`soundfonts`](/soundfonts): A module to parse soundfonts to be used in XSynth. +- [`realtime`](/realtime): The real-time rendering module within XSynth. +- [`render`](/render): A command line utility for rendering MIDIs to audio using XSynth. +- [`kdmapi`](/kdmapi): A cdylib wrapper around XSynth to act as a drop in replacement for OmniMIDI/KDMAPI. +- [`interface`](/interface): A MIDI interface for XSynth. ## Demos diff --git a/interface/Cargo.toml b/interface/Cargo.toml new file mode 100644 index 00000000..61b3647d --- /dev/null +++ b/interface/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "xsynth-interface" +version.workspace = true +license.workspace = true +edition.workspace = true +homepage.workspace = true +repository.workspace = true +keywords.workspace = true +categories.workspace = true + +[dependencies] +xsynth-core = { workspace = true, features = ["serde"] } +xsynth-realtime = { workspace = true, features = ["serde"] } +midir = { version = "0.10.1" } +cfg-if = "1.0.0" +serde_json = "1.0.122" +serde = { version = "1.0.206", features = ["derive"] } +hotwatch = "0.5.0" +directories = "6.0.0" diff --git a/interface/README.md b/interface/README.md new file mode 100644 index 00000000..66c50f78 --- /dev/null +++ b/interface/README.md @@ -0,0 +1,3 @@ +# xsynth-interface + +A MIDI interface for XSynth. By using midir, it can be used to send MIDI events to XSynth without the need of KDMAPI or direct integration with XSynth. diff --git a/interface/src/main.rs b/interface/src/main.rs new file mode 100644 index 00000000..244b0836 --- /dev/null +++ b/interface/src/main.rs @@ -0,0 +1,93 @@ +use std::error::Error; +use std::io::stdin; + +use hotwatch::{Event, EventKind, Hotwatch}; +use midir::os::unix::VirtualInput; +use midir::{Ignore, MidiInput}; +use std::{thread, time::Duration}; +use xsynth_core::channel::{ChannelConfigEvent, ChannelEvent}; +use xsynth_realtime::{RealtimeSynth, SynthEvent}; + +mod parsers; +use parsers::*; + +fn main() { + match run() { + Ok(_) => (), + Err(err) => println!("Error: {}", err), + } +} + +fn run() -> Result<(), Box> { + let config = Config::::new().load().unwrap(); + let sflist = Config::::new().load().unwrap(); + + let realtime_synth = RealtimeSynth::open_with_default_output(config.get_synth_config()); + let mut sender = realtime_synth.get_sender_ref().clone(); + let params = realtime_synth.stream_params(); + + sender.send_event(SynthEvent::AllChannels(ChannelEvent::Config( + ChannelConfigEvent::SetLayerCount(config.get_layers()), + ))); + sender.send_event(SynthEvent::AllChannels(ChannelEvent::Config( + ChannelConfigEvent::SetSoundfonts(sflist.create_sfbase_vector(params)), + ))); + + let mut midi_in = MidiInput::new("XSynth")?; + midi_in.ignore(Ignore::None); + + // _conn_in needs to be a named parameter, because it needs to be kept alive until the end of the scope + let mut sender_thread = sender.clone(); + let _conn_in = midi_in.create_virtual( + "XSynth MIDI In", + move |_, message, _| { + //println!("{}: {:?} (len = {})", stamp, message, message.len()); + //Send the MIDI message to the synth as raw bytes + sender_thread.send_event_u32( + message.get(0).copied().unwrap_or(0) as u32 + | (message.get(1).copied().unwrap_or(0) as u32) << 8 + | (message.get(2).copied().unwrap_or(0) as u32) << 16, + ); + }, + (), + )?; + + let mut hotwatch = Hotwatch::new_with_custom_delay(Duration::from_millis(500)).unwrap(); + + // Watch for config changes and apply them + let mut sender_thread = sender.clone(); + hotwatch + .watch(Config::::path(), move |event: Event| { + if let EventKind::Modify(_) = event.kind { + thread::sleep(Duration::from_millis(10)); + let layers = Config::::new().load().unwrap().get_layers(); + sender_thread.send_event(SynthEvent::AllChannels(ChannelEvent::Config( + ChannelConfigEvent::SetLayerCount(layers), + ))); + } + }) + .unwrap(); + + // Watch for soundfont list changes and apply them + let mut sender_thread = sender.clone(); + hotwatch + .watch(Config::::path(), move |event: Event| { + if let EventKind::Modify(_) = event.kind { + thread::sleep(Duration::from_millis(10)); + let sfs = Config::::new() + .load() + .unwrap() + .create_sfbase_vector(params); + sender_thread.send_event(SynthEvent::AllChannels(ChannelEvent::Config( + ChannelConfigEvent::SetSoundfonts(sfs), + ))); + } + }) + .unwrap(); + + println!("Press any key to exit..."); + let mut input = String::new(); + stdin().read_line(&mut input)?; + println!("Shutting down..."); + Ok(()) +} diff --git a/interface/src/parsers.rs b/interface/src/parsers.rs new file mode 100644 index 00000000..9cd548d9 --- /dev/null +++ b/interface/src/parsers.rs @@ -0,0 +1,81 @@ +use serde::{Deserialize, Serialize}; +use std::{fs::File, io::prelude::*, marker::PhantomData, path::PathBuf}; + +mod soundfonts; +pub use soundfonts::SFList; + +mod settings; +pub use settings::Settings; + +const CONFIG_DIR: &str = "xsynth"; + +pub trait ConfigPath { + fn filename() -> PathBuf; +} + +pub struct Config +where + T: Default + Serialize + for<'a> Deserialize<'a> + ConfigPath, +{ + path: PathBuf, + _config: PhantomData, +} + +impl Config +where + T: Default + Serialize + for<'a> Deserialize<'a> + ConfigPath, +{ + pub fn path() -> PathBuf { + match directories::BaseDirs::new() { + Some(dirs) => { + let mut path = dirs.config_dir().to_path_buf(); + path.push(CONFIG_DIR); + std::fs::create_dir_all(&path).unwrap(); + path.push(T::filename()); + path + } + None => PathBuf::from("./"), + } + } + + pub fn new() -> Self { + Self { + path: Config::::path(), + _config: PhantomData, + } + } + + fn load_from_file(&self) -> Result { + let mut file = File::open(&self.path).map_err(|e| format!("IO error: {e}"))?; + let mut contents = String::new(); + file.read_to_string(&mut contents) + .map_err(|e| format!("Loading error: {e}"))?; + serde_json::from_str(&contents).map_err(|e| format!("Parsing error: {e}")) + } + + fn save(&self, config: &T) -> Result<(), String> { + let contents = + serde_json::to_string_pretty(config).map_err(|e| format!("Parsing error: {e}"))?; + let mut file = File::create(&self.path).map_err(|e| format!("IO error: {e}"))?; + file.write_all(contents.as_bytes()) + .map_err(|e| format!("Saving error: {e}"))?; + + Ok(()) + } + + fn create_empty(&self) -> Result<(), String> { + self.save(&T::default()) + } + + pub fn load(&self) -> Result { + let path = &self.path; + if !path.exists() { + self.create_empty()?; + } + self.load_from_file() + } + + pub fn repair(&self) -> Result<(), String> { + self.save(&self.load()?) + } +} diff --git a/interface/src/parsers/settings.rs b/interface/src/parsers/settings.rs new file mode 100644 index 00000000..6f7607b1 --- /dev/null +++ b/interface/src/parsers/settings.rs @@ -0,0 +1,56 @@ +use super::ConfigPath; +use serde::{Deserialize, Serialize}; +use std::{ops::RangeInclusive, path::PathBuf}; +use xsynth_core::channel::ChannelInitOptions; +use xsynth_realtime::{SynthFormat, ThreadCount, XSynthRealtimeConfig}; + +#[derive(Clone, Serialize, Deserialize)] +#[serde(default)] +pub struct Settings { + // Channel options + layers: Option, + fade_out_killing: bool, + + // Realtime synth options + render_window_ms: f64, + multithreading: ThreadCount, + ignore_range: RangeInclusive, +} + +impl Default for Settings { + fn default() -> Self { + let chandef = ChannelInitOptions::default(); + + Self { + layers: Some(4), + fade_out_killing: chandef.fade_out_killing, + render_window_ms: 10.0, + multithreading: ThreadCount::None, + ignore_range: 0..=0, + } + } +} + +impl Settings { + pub fn get_layers(&self) -> Option { + self.layers + } + + pub fn get_synth_config(&self) -> XSynthRealtimeConfig { + XSynthRealtimeConfig { + channel_init_options: ChannelInitOptions { + fade_out_killing: self.fade_out_killing, + }, + render_window_ms: self.render_window_ms, + format: SynthFormat::Midi, + multithreading: self.multithreading, + ignore_range: self.ignore_range.clone(), + } + } +} + +impl ConfigPath for Settings { + fn filename() -> PathBuf { + "settings.json".into() + } +} diff --git a/interface/src/parsers/soundfonts.rs b/interface/src/parsers/soundfonts.rs new file mode 100644 index 00000000..db4acf0a --- /dev/null +++ b/interface/src/parsers/soundfonts.rs @@ -0,0 +1,74 @@ +use super::ConfigPath; +use serde::{Deserialize, Serialize}; +use std::{path::PathBuf, sync::Arc}; +use xsynth_core::{ + soundfont::{SampleSoundfont, SoundfontBase, SoundfontInitOptions}, + AudioStreamParams, +}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(default)] +pub struct SFDescriptor { + pub path: PathBuf, + pub enabled: bool, + pub options: SoundfontInitOptions, +} + +impl Default for SFDescriptor { + fn default() -> Self { + Self { + path: PathBuf::new(), + enabled: true, + options: Default::default(), + } + } +} + +impl SFDescriptor { + pub fn path(&self) -> Option { + let path = PathBuf::from(&self.path); + if path.exists() && self.enabled { + Some(path) + } else { + None + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(default)] +pub struct SFList { + soundfonts: Vec, +} + +impl Default for SFList { + fn default() -> Self { + Self { + soundfonts: vec![SFDescriptor::default()], + } + } +} + +impl SFList { + pub fn create_sfbase_vector( + self, + stream_params: AudioStreamParams, + ) -> Vec> { + let mut out: Vec> = Vec::new(); + for sf in self.soundfonts { + if let Some(path) = sf.path() { + match SampleSoundfont::new(path, stream_params, sf.options) { + Ok(sf) => out.push(Arc::new(sf)), + Err(e) => println!("Error loading soundfont: {e}"), + } + } + } + out + } +} + +impl ConfigPath for SFList { + fn filename() -> PathBuf { + "soundfonts.json".into() + } +} diff --git a/kdmapi/Cargo.toml b/kdmapi/Cargo.toml index 386aea6c..e9750faa 100644 --- a/kdmapi/Cargo.toml +++ b/kdmapi/Cargo.toml @@ -25,4 +25,4 @@ cfg-if = "1.0.0" serde_json = "1.0.122" serde = { version = "1.0.206", features = ["derive"] } hotwatch = "0.5.0" -directories = "5.0.1" \ No newline at end of file +directories = "6.0.0" diff --git a/kdmapi/README.md b/kdmapi/README.md index e2b6942a..d44055c0 100644 --- a/kdmapi/README.md +++ b/kdmapi/README.md @@ -6,7 +6,7 @@ A cdylib wrapper around XSynth to act as a drop in replacement for OmniMIDI/KDMA 1) Alternatively you can build the library yourself by cloning the repo and compiling with Cargo. 2) Place it in the same directory as your KDMAPI aware software of choice. -Upon loading the library, the following two files will be generated under `%userprofile%/AppData/Roaming/xsynth-kdmapi` (on Windows): +Upon loading the library, the following two files will be generated under `%userprofile%/AppData/Roaming/xsynth` (on Windows): ### `settings.json` The synthesizer settings. Fields: diff --git a/kdmapi/src/parsers.rs b/kdmapi/src/parsers.rs index 21592d8f..9cd548d9 100644 --- a/kdmapi/src/parsers.rs +++ b/kdmapi/src/parsers.rs @@ -7,7 +7,7 @@ pub use soundfonts::SFList; mod settings; pub use settings::Settings; -const CONFIG_DIR: &str = "xsynth-kdmapi"; +const CONFIG_DIR: &str = "xsynth"; pub trait ConfigPath { fn filename() -> PathBuf; From b535bd65b4024e76b14b09e398a47f97108a53b8 Mon Sep 17 00:00:00 2001 From: Kaydax Date: Thu, 13 Mar 2025 18:29:02 -0400 Subject: [PATCH 2/2] Temp disable windows support for now --- interface/src/main.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/interface/src/main.rs b/interface/src/main.rs index 244b0836..2dec37d6 100644 --- a/interface/src/main.rs +++ b/interface/src/main.rs @@ -1,8 +1,10 @@ use std::error::Error; use std::io::stdin; -use hotwatch::{Event, EventKind, Hotwatch}; +#[cfg(not(target_os = "windows"))] use midir::os::unix::VirtualInput; + +use hotwatch::{Event, EventKind, Hotwatch}; use midir::{Ignore, MidiInput}; use std::{thread, time::Duration}; use xsynth_core::channel::{ChannelConfigEvent, ChannelEvent}; @@ -18,6 +20,7 @@ fn main() { } } +#[cfg(not(target_os = "windows"))] fn run() -> Result<(), Box> { let config = Config::::new().load().unwrap(); let sflist = Config::::new().load().unwrap(); @@ -91,3 +94,9 @@ fn run() -> Result<(), Box> { println!("Shutting down..."); Ok(()) } + +#[cfg(target_os = "windows")] +fn run() -> Result<(), Box> { + println!("xsynth-interface is not supported on Windows."); + Ok(()) +}