Skip to main content

midi_io/
connection.rs

1use std::pin::Pin;
2use std::sync::Arc;
3use std::task::Context;
4use std::task::Poll;
5
6use futures_channel::mpsc;
7use futures_util::stream::select;
8use futures_util::Stream;
9use futures_util::StreamExt;
10
11use crate::platform::PlatformClient;
12use crate::port::VirtualPortId;
13use crate::Decoded;
14use crate::Destination;
15use crate::DestinationChange;
16use crate::Error;
17use crate::MidiMessage;
18use crate::PortId;
19use crate::RawMidiMessage;
20use crate::Source;
21use crate::SourceChange;
22use crate::SysEx;
23
24#[derive(Debug, Clone)]
25pub struct Timed<T> {
26    pub timestamp: std::time::Instant,
27    pub payload: T,
28}
29
30impl<T> Timed<T> {
31    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Timed<U> {
32        Timed {
33            timestamp: self.timestamp,
34            payload: f(self.payload),
35        }
36    }
37}
38
39#[derive(Debug)]
40enum ConnectionId {
41    Source(PortId),
42    Destination(PortId),
43    VirtualSource(VirtualPortId),
44    VirtualDestination(VirtualPortId),
45}
46
47#[derive(Debug)]
48pub(crate) struct ConnectionGuard {
49    target: ConnectionId,
50    platform: Arc<PlatformClient>,
51}
52
53impl Drop for ConnectionGuard {
54    fn drop(&mut self) {
55        match &self.target {
56            ConnectionId::Source(port) => self.platform.disconnect(*port),
57            ConnectionId::Destination(port) => self.platform.disconnect_destination(*port),
58            ConnectionId::VirtualSource(id) => self.platform.destroy_virtual_source(*id),
59            ConnectionId::VirtualDestination(id) => self.platform.destroy_virtual_destination(*id),
60        }
61    }
62}
63
64#[derive(Debug)]
65struct ReceiveStreams {
66    message_rx: mpsc::Receiver<Timed<MidiMessage>>,
67    sysex_rx: mpsc::Receiver<Timed<SysEx>>,
68    error_rx: mpsc::Receiver<Timed<Error>>,
69    guard: Arc<ConnectionGuard>,
70}
71
72impl ReceiveStreams {
73    fn into_streams(self) -> Streams {
74        Streams {
75            messages: MessageStream {
76                inner: self.message_rx,
77                _guard: self.guard.clone(),
78            },
79            sysex: SysexStream {
80                inner: self.sysex_rx,
81                _guard: self.guard.clone(),
82            },
83            errors: ErrorStream {
84                inner: self.error_rx,
85                _guard: self.guard,
86            },
87        }
88    }
89
90    fn into_messages(self) -> MessageStream {
91        MessageStream {
92            inner: self.message_rx,
93            _guard: self.guard,
94        }
95    }
96
97    fn into_sysex(self) -> SysexStream {
98        SysexStream {
99            inner: self.sysex_rx,
100            _guard: self.guard,
101        }
102    }
103
104    fn into_errors(self) -> ErrorStream {
105        ErrorStream {
106            inner: self.error_rx,
107            _guard: self.guard,
108        }
109    }
110
111    fn into_events(self) -> EventStream {
112        EventStream::new(self.message_rx, self.sysex_rx, self.error_rx, self.guard)
113    }
114}
115
116#[derive(Debug)]
117pub struct SourceConnection {
118    streams: ReceiveStreams,
119}
120
121impl SourceConnection {
122    pub(crate) fn new(
123        message_rx: mpsc::Receiver<Timed<MidiMessage>>,
124        sysex_rx: mpsc::Receiver<Timed<SysEx>>,
125        error_rx: mpsc::Receiver<Timed<Error>>,
126        port: PortId,
127        platform: Arc<crate::platform::PlatformClient>,
128    ) -> Self {
129        Self {
130            streams: ReceiveStreams {
131                message_rx,
132                sysex_rx,
133                error_rx,
134                guard: Arc::new(ConnectionGuard {
135                    target: ConnectionId::Source(port),
136                    platform,
137                }),
138            },
139        }
140    }
141
142    pub fn into_streams(self) -> Streams {
143        self.streams.into_streams()
144    }
145
146    pub fn into_messages(self) -> MessageStream {
147        self.streams.into_messages()
148    }
149
150    pub fn into_sysex(self) -> SysexStream {
151        self.streams.into_sysex()
152    }
153
154    pub fn into_errors(self) -> ErrorStream {
155        self.streams.into_errors()
156    }
157
158    pub fn into_events(self) -> EventStream {
159        self.streams.into_events()
160    }
161}
162
163#[derive(Debug)]
164pub struct MessageStream {
165    inner: mpsc::Receiver<Timed<MidiMessage>>,
166    _guard: Arc<ConnectionGuard>,
167}
168
169impl MessageStream {
170    pub async fn recv(&mut self) -> Option<Timed<MidiMessage>> {
171        self.next().await
172    }
173}
174
175impl Stream for MessageStream {
176    type Item = Timed<MidiMessage>;
177
178    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
179        Pin::new(&mut self.inner).poll_next(cx)
180    }
181}
182
183#[derive(Debug)]
184pub struct SysexStream {
185    inner: mpsc::Receiver<Timed<SysEx>>,
186    _guard: Arc<ConnectionGuard>,
187}
188
189impl SysexStream {
190    pub async fn recv(&mut self) -> Option<Timed<SysEx>> {
191        self.next().await
192    }
193}
194
195impl Stream for SysexStream {
196    type Item = Timed<SysEx>;
197
198    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
199        Pin::new(&mut self.inner).poll_next(cx)
200    }
201}
202
203#[derive(Debug)]
204pub struct ErrorStream {
205    inner: mpsc::Receiver<Timed<Error>>,
206    _guard: Arc<ConnectionGuard>,
207}
208
209impl ErrorStream {
210    pub async fn recv(&mut self) -> Option<Timed<Error>> {
211        self.next().await
212    }
213}
214
215impl Stream for ErrorStream {
216    type Item = Timed<Error>;
217
218    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
219        Pin::new(&mut self.inner).poll_next(cx)
220    }
221}
222
223#[derive(Debug)]
224pub struct Streams {
225    pub messages: MessageStream,
226    pub sysex: SysexStream,
227    pub errors: ErrorStream,
228}
229
230#[allow(clippy::type_complexity)]
231pub struct EventStream {
232    inner: Pin<Box<dyn Stream<Item = Timed<Result<Decoded, Error>>> + Send>>,
233    _guard: Arc<ConnectionGuard>,
234}
235
236impl EventStream {
237    fn new(
238        message_rx: mpsc::Receiver<Timed<MidiMessage>>,
239        sysex_rx: mpsc::Receiver<Timed<SysEx>>,
240        error_rx: mpsc::Receiver<Timed<Error>>,
241        guard: Arc<ConnectionGuard>,
242    ) -> Self {
243        let messages = message_rx.map(|t| t.map(|m| Ok::<Decoded, Error>(Decoded::Message(m))));
244        let sysex = sysex_rx.map(|t| t.map(|s| Ok::<Decoded, Error>(Decoded::SysEx(s))));
245        let errors = error_rx.map(|t| t.map(Err::<Decoded, Error>));
246        Self {
247            inner: Box::pin(select(select(messages, sysex), errors)),
248            _guard: guard,
249        }
250    }
251
252    pub async fn recv(&mut self) -> Option<Timed<Result<Decoded, Error>>> {
253        self.next().await
254    }
255}
256
257impl Stream for EventStream {
258    type Item = Timed<Result<Decoded, Error>>;
259
260    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
261        self.inner.as_mut().poll_next(cx)
262    }
263}
264
265impl std::fmt::Debug for EventStream {
266    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267        f.debug_struct("EventStream").finish_non_exhaustive()
268    }
269}
270
271#[derive(Debug, Clone)]
272pub struct DestinationConnection {
273    pub(crate) port: PortId,
274    pub(crate) guard: Arc<ConnectionGuard>,
275}
276
277impl DestinationConnection {
278    pub(crate) fn new(port: PortId, platform: Arc<crate::platform::PlatformClient>) -> Self {
279        Self {
280            port,
281            guard: Arc::new(ConnectionGuard {
282                target: ConnectionId::Destination(port),
283                platform,
284            }),
285        }
286    }
287
288    pub async fn send(&self, msg: &MidiMessage) -> Result<(), Error> {
289        let raw = RawMidiMessage::from(msg);
290        self.guard.platform.send_midi(self.port, raw).await
291    }
292
293    pub async fn send_sysex(&self, sysex: &SysEx) -> Result<(), Error> {
294        self.guard
295            .platform
296            .send_sysex(self.port, sysex.to_wire_bytes())
297            .await
298    }
299}
300
301#[derive(Debug)]
302pub struct VirtualDestination {
303    streams: ReceiveStreams,
304    port: PortId,
305    name: String,
306}
307
308impl VirtualDestination {
309    pub(crate) fn new(
310        message_rx: mpsc::Receiver<Timed<MidiMessage>>,
311        sysex_rx: mpsc::Receiver<Timed<SysEx>>,
312        error_rx: mpsc::Receiver<Timed<Error>>,
313        id: VirtualPortId,
314        port: PortId,
315        name: String,
316        platform: Arc<crate::platform::PlatformClient>,
317    ) -> Self {
318        Self {
319            streams: ReceiveStreams {
320                message_rx,
321                sysex_rx,
322                error_rx,
323                guard: Arc::new(ConnectionGuard {
324                    target: ConnectionId::VirtualDestination(id),
325                    platform,
326                }),
327            },
328            port,
329            name,
330        }
331    }
332
333    pub fn as_destination(&self) -> Destination {
334        Destination {
335            id: self.port,
336            name: self.name.clone(),
337            is_virtual: true,
338        }
339    }
340
341    pub fn into_streams(self) -> Streams {
342        self.streams.into_streams()
343    }
344
345    pub fn into_messages(self) -> MessageStream {
346        self.streams.into_messages()
347    }
348
349    pub fn into_sysex(self) -> SysexStream {
350        self.streams.into_sysex()
351    }
352
353    pub fn into_errors(self) -> ErrorStream {
354        self.streams.into_errors()
355    }
356
357    pub fn into_events(self) -> EventStream {
358        self.streams.into_events()
359    }
360}
361
362#[derive(Debug, Clone)]
363pub struct VirtualSource {
364    pub(crate) id: VirtualPortId,
365    pub(crate) port: PortId,
366    pub(crate) name: String,
367    pub(crate) guard: Arc<ConnectionGuard>,
368}
369
370impl VirtualSource {
371    pub(crate) fn new(
372        id: VirtualPortId,
373        port: PortId,
374        name: String,
375        platform: Arc<crate::platform::PlatformClient>,
376    ) -> Self {
377        Self {
378            id,
379            port,
380            name,
381            guard: Arc::new(ConnectionGuard {
382                target: ConnectionId::VirtualSource(id),
383                platform,
384            }),
385        }
386    }
387
388    pub fn as_source(&self) -> Source {
389        Source {
390            id: self.port,
391            name: self.name.clone(),
392            is_virtual: true,
393        }
394    }
395
396    pub async fn send(&self, msg: &MidiMessage) -> Result<(), Error> {
397        let raw = RawMidiMessage::from(msg);
398        self.guard.platform.send_virtual_midi(self.id, raw).await
399    }
400
401    pub async fn send_sysex(&self, sysex: &SysEx) -> Result<(), Error> {
402        self.guard
403            .platform
404            .send_virtual_sysex(self.id, sysex.to_wire_bytes())
405            .await
406    }
407}
408
409#[derive(Debug)]
410pub struct SourceChanges(pub(crate) mpsc::UnboundedReceiver<SourceChange>);
411
412impl SourceChanges {
413    pub async fn recv(&mut self) -> Option<SourceChange> {
414        self.next().await
415    }
416}
417
418impl Stream for SourceChanges {
419    type Item = SourceChange;
420
421    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
422        Pin::new(&mut self.0).poll_next(cx)
423    }
424}
425
426#[derive(Debug)]
427pub struct DestinationChanges(pub(crate) mpsc::UnboundedReceiver<DestinationChange>);
428
429impl DestinationChanges {
430    pub async fn recv(&mut self) -> Option<DestinationChange> {
431        self.next().await
432    }
433}
434
435impl Stream for DestinationChanges {
436    type Item = DestinationChange;
437
438    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
439        Pin::new(&mut self.0).poll_next(cx)
440    }
441}