Almost mocked
Some checks failed
Continuous integration / Build and test (push) Failing after 47s

This commit is contained in:
GHOSCHT 2024-12-25 18:26:45 +01:00
parent 809e0c5b10
commit 443e77ab46
Signed by: ghoscht
GPG key ID: 2C2C1C62A5388E82
4 changed files with 83 additions and 58 deletions

View file

@ -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());
}
}

View file

@ -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;
} }

View file

@ -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 {

View file

@ -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");
} }