This commit is contained in:
parent
809e0c5b10
commit
443e77ab46
4 changed files with 83 additions and 58 deletions
|
@ -1,11 +1,8 @@
|
||||||
use crate::{config::NanoKeys, interaction_server::InteractionServer};
|
use crate::{config::NanoKeys, interaction_server::InteractionServer};
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use midir::MidiInput;
|
use midir::MidiInput;
|
||||||
use shaku::{module, HasComponent, Interface};
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use super::midi_client::MidiPort;
|
use super::midi_client::{MidiClient, MidiPort, MockMidiClient, MockMidiPort};
|
||||||
use super::midi_service::MidiService;
|
use super::midi_service::MidiService;
|
||||||
use super::midi_service_impl::{MidiServiceImpl, MidiServiceImplParameters};
|
use super::midi_service_impl::{MidiServiceImpl, MidiServiceImplParameters};
|
||||||
use super::midir_client_impl::{MidirClientImpl, MidirPortImpl};
|
use super::midir_client_impl::{MidirClientImpl, MidirPortImpl};
|
||||||
|
@ -13,51 +10,32 @@ use super::midir_client_impl::{MidirClientImpl, MidirPortImpl};
|
||||||
const CLIENT_NAME: &str = "PicoKontroller";
|
const CLIENT_NAME: &str = "PicoKontroller";
|
||||||
const PORT_NAME: &str = "PicoController Input";
|
const PORT_NAME: &str = "PicoController Input";
|
||||||
|
|
||||||
pub struct MidiClient {
|
//pub struct MidiClient {
|
||||||
pub device_name: String,
|
// pub device_name: String,
|
||||||
pub out_channel: Sender<KeyEvent>,
|
// pub out_channel: Sender<KeyEvent>,
|
||||||
}
|
//}
|
||||||
|
|
||||||
pub type KeyEvent = (NanoKeys, KeyState);
|
pub type KeyEvent = (NanoKeys, KeyState);
|
||||||
pub type KeyState = u8;
|
pub type KeyState = u8;
|
||||||
|
|
||||||
module! {
|
|
||||||
MyModule<MP: MidiPort + Interface> {
|
|
||||||
components = [MidiServiceImpl<MidirPortImpl>, MidirClientImpl],
|
|
||||||
providers = [],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MidiClient {
|
//impl MidiClient {
|
||||||
pub fn new(device_name: String, out_channel: Sender<KeyEvent>) -> MidiClient {
|
// pub fn new(device_name: String, out_channel: Sender<KeyEvent>) -> MidiClient {
|
||||||
MidiClient {
|
// MidiClient {
|
||||||
device_name,
|
// device_name,
|
||||||
out_channel,
|
// out_channel,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
pub fn start(self) -> () {
|
// pub fn start(self) -> () {
|
||||||
let module: MyModule<MidirPortImpl> = MyModule::builder()
|
// }
|
||||||
.with_component_parameters::<MidiServiceImpl<MidirPortImpl>>(
|
//}
|
||||||
MidiServiceImplParameters::<MidirPortImpl> {
|
//
|
||||||
device_name: "nanoKONTROL2".to_string(),
|
//pub fn list_ports() -> () {
|
||||||
out_channel: self.out_channel,
|
// let midi_in = MidiInput::new(CLIENT_NAME).expect("Creating MIDI device failed");
|
||||||
phantom: PhantomData,
|
// let in_ports = midi_in.ports();
|
||||||
},
|
// println!("All available MIDI devices:");
|
||||||
)
|
// for (_, p) in in_ports.iter().enumerate() {
|
||||||
.build();
|
// println!("{}", midi_in.port_name(p).unwrap());
|
||||||
|
// }
|
||||||
let service: Arc<dyn MidiService<MidirPortImpl>> = module.resolve();
|
//}
|
||||||
let handle = service.start();
|
|
||||||
let _ = handle.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn list_ports() -> () {
|
|
||||||
let midi_in = MidiInput::new(CLIENT_NAME).expect("Creating MIDI device failed");
|
|
||||||
let in_ports = midi_in.ports();
|
|
||||||
println!("All available MIDI devices:");
|
|
||||||
for (_, p) in in_ports.iter().enumerate() {
|
|
||||||
println!("{}", midi_in.port_name(p).unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
use shaku::{self, Interface};
|
use shaku::{self, Interface};
|
||||||
|
|
||||||
pub type MidiConnectionCallback = Box<dyn Fn(&[u8]) + Send>;
|
pub type MidiConnectionCallback = Box<dyn Fn(&[u8]) + Send>;
|
||||||
|
|
||||||
#[cfg_attr(test, mockall::automock)]
|
#[mockall::automock]
|
||||||
pub trait MidiClient<MP: MidiPort + Interface>: Interface {
|
pub trait MidiClient<MP: MidiPort + Interface>: Interface {
|
||||||
fn ports(&self) -> Vec<MP>;
|
fn ports(&self) -> Vec<MP>;
|
||||||
fn connect(&self, port: &MP, port_name: &str, callback: MidiConnectionCallback) -> ();
|
fn connect(&self, port: &MP, port_name: &str, callback: MidiConnectionCallback) -> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(test, mockall::automock)]
|
#[mockall::automock]
|
||||||
pub trait MidiPort: Interface {
|
pub trait MidiPort: Interface + Send{
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use midir::{Ignore, MidiInput, MidiInputPort};
|
||||||
use shaku::{self, Component};
|
use shaku::{self, Component};
|
||||||
|
|
||||||
use super::midi_client::{MidiClient, MidiConnectionCallback, MidiPort};
|
use super::midi_client::{MidiClient, MidiConnectionCallback, MidiPort};
|
||||||
use std::time;
|
use std::{any::Any, time};
|
||||||
|
|
||||||
fn create_input(client_name: &str) -> MidiInput {
|
fn create_input(client_name: &str) -> MidiInput {
|
||||||
let mut input = MidiInput::new(client_name).expect("Creating MIDI device failed");
|
let mut input = MidiInput::new(client_name).expect("Creating MIDI device failed");
|
||||||
|
@ -56,6 +56,9 @@ impl MidiPort for MidirPortImpl {
|
||||||
let midi_in = create_input(&self.client_name);
|
let midi_in = create_input(&self.client_name);
|
||||||
midi_in.port_name(&self.port).unwrap()
|
midi_in.port_name(&self.port).unwrap()
|
||||||
}
|
}
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MidirPortImpl {
|
impl MidirPortImpl {
|
||||||
|
|
56
src/main.rs
56
src/main.rs
|
@ -10,11 +10,18 @@ mod controllers {
|
||||||
mod clients;
|
mod clients;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use clients::midi::MidiClient;
|
use clients::midi::KeyEvent;
|
||||||
use crossbeam_channel::unbounded;
|
use clients::midi_client::{MidiClient, MidiPort, MockMidiClient, MockMidiPort};
|
||||||
|
use clients::midi_service::MidiService;
|
||||||
|
use clients::midi_service_impl::{MidiServiceImpl, MidiServiceImplParameters};
|
||||||
|
use clients::midir_client_impl::{MidirClientImpl, MidirPortImpl};
|
||||||
|
use crossbeam_channel::{unbounded, Sender};
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
use std::{path::PathBuf, process::exit, sync::Arc};
|
use std::{path::PathBuf, process::exit, sync::Arc};
|
||||||
|
|
||||||
|
use shaku::{module, HasComponent, Interface, ModuleBuilder};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(version, about, long_about = None)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
|
@ -24,12 +31,32 @@ struct Cli {
|
||||||
list_mpris: bool,
|
list_mpris: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module! {
|
||||||
|
MyModule<MP: MidiPort + Interface> {
|
||||||
|
components = [MidiServiceImpl<MidirPortImpl>, MidirClientImpl],
|
||||||
|
providers = [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_module(
|
||||||
|
device_name: String,
|
||||||
|
out_channel: Sender<KeyEvent>,
|
||||||
|
) -> ModuleBuilder<MyModule<MidirPortImpl>> {
|
||||||
|
MyModule::builder().with_component_parameters::<MidiServiceImpl<MidirPortImpl>>(
|
||||||
|
MidiServiceImplParameters::<MidirPortImpl> {
|
||||||
|
device_name,
|
||||||
|
out_channel,
|
||||||
|
phantom: PhantomData,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
if cli.list_midi {
|
if cli.list_midi {
|
||||||
clients::midi::list_ports();
|
//clients::midi::list_ports();
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if cli.list_mpris {
|
} else if cli.list_mpris {
|
||||||
controllers::mpris::list_players();
|
controllers::mpris::list_players();
|
||||||
|
@ -42,10 +69,25 @@ fn main() {
|
||||||
let arc_cfg = Arc::new(cfg);
|
let arc_cfg = Arc::new(cfg);
|
||||||
|
|
||||||
let (sender, receiver) = unbounded::<clients::midi::KeyEvent>();
|
let (sender, receiver) = unbounded::<clients::midi::KeyEvent>();
|
||||||
let midi = MidiClient::new(arc_cfg.general.midi_device.clone(), sender);
|
|
||||||
|
let mut client_mock = MockMidiClient::<MockMidiPort>::new();
|
||||||
|
let mut port_mock = MockMidiPort::new();
|
||||||
|
port_mock
|
||||||
|
.expect_name()
|
||||||
|
.times(1)
|
||||||
|
.returning(|| "nanoKONTROL2:nanoKONTROL2 nanoKONTROL2 _ CTR 28:0".to_string());
|
||||||
|
client_mock
|
||||||
|
.expect_ports()
|
||||||
|
.times(1)
|
||||||
|
.returning(|| vec![port_mock]);
|
||||||
|
|
||||||
|
let module: MyModule<MockMidiPort> = MyModule::builder()
|
||||||
|
.with_component_override::<dyn MidiClient<MockMidiPort>>(Box::new(client_mock))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let service: Arc<dyn MidiService<MidirPortImpl>> = module.resolve();
|
||||||
|
let handle = service.start();
|
||||||
|
let _ = handle.join();
|
||||||
|
|
||||||
router::run(receiver, Arc::clone(&arc_cfg));
|
router::run(receiver, Arc::clone(&arc_cfg));
|
||||||
|
|
||||||
midi.start();
|
|
||||||
println!("fooo");
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue