sim_lib_stream_host/
midi_live_eval_site.rs1use std::convert::Infallible;
4
5use sim_kernel::{Error, Result, Symbol};
6use sim_lib_midi_core::{MidiSink, MidiSource};
7use sim_lib_midi_live::{LiveMidiDirection, LiveMidiError, LiveMidiSession};
8
9use crate::eval_site::StreamEvalSite;
10use crate::placement::{DeviceDirection, DeviceKind, DeviceRecord, Placement};
11
12pub struct MidiLiveEvalSite {
14 record: DeviceRecord,
15 session: LiveMidiSession,
16 site: Box<dyn StreamEvalSite>,
17}
18
19impl MidiLiveEvalSite {
20 pub fn from_eval_site(id: &Symbol, site: Box<dyn StreamEvalSite>) -> Result<Self> {
22 let record = site.device_record().clone();
23 if record.kind != DeviceKind::Midi {
24 site.close()?;
25 return Err(Error::Eval(format!("open_live: device '{id}' is not MIDI")));
26 }
27 let direction = live_direction(record.direction);
28 let session = LiveMidiSession::modeled(direction).map_err(live_error)?;
29 Ok(Self {
30 record,
31 session,
32 site,
33 })
34 }
35
36 pub fn source_mut(&mut self) -> &mut dyn MidiSource<Err = Infallible> {
38 self.session.source_mut()
39 }
40
41 pub fn sink_mut(&mut self) -> Option<&mut dyn MidiSink<Err = Infallible>> {
43 self.session.sink_mut()
44 }
45}
46
47impl StreamEvalSite for MidiLiveEvalSite {
48 fn placement(&self) -> &Placement {
49 &self.record.placement
50 }
51
52 fn device_record(&self) -> &DeviceRecord {
53 &self.record
54 }
55
56 fn close(self: Box<Self>) -> Result<()> {
57 let Self { session, site, .. } = *self;
58 session.close().map_err(live_error)?;
59 site.close()
60 }
61}
62
63fn live_direction(direction: DeviceDirection) -> LiveMidiDirection {
64 match direction {
65 DeviceDirection::Input => LiveMidiDirection::Source,
66 DeviceDirection::Output => LiveMidiDirection::Sink,
67 DeviceDirection::Duplex => LiveMidiDirection::Duplex,
68 }
69}
70
71fn live_error(err: LiveMidiError) -> Error {
72 Error::Eval(format!("midi live: {err}"))
73}