1- use caw_core:: { Sig , SigT } ;
1+ use caw_core:: { Buf , Sig , SigCtx , SigT } ;
22use caw_midi:: MidiMessages ;
33use midly:: { MidiMessage , live:: LiveEvent , num:: u4} ;
44use std:: {
55 io,
6- net:: { ToSocketAddrs , UdpSocket } ,
6+ net:: { Ipv4Addr , SocketAddr , ToSocketAddrs , UdpSocket } ,
77} ;
88
99const BUF_SIZE : usize = 256 ;
@@ -26,6 +26,14 @@ impl MidiLiveUdp {
2626 Ok ( Self { socket, buf } )
2727 }
2828
29+ pub fn new_unspecified ( ) -> anyhow:: Result < Self > {
30+ Self :: new ( ( Ipv4Addr :: UNSPECIFIED , 0 ) )
31+ }
32+
33+ pub fn local_socket_address ( & self ) -> anyhow:: Result < SocketAddr > {
34+ Ok ( self . socket . local_addr ( ) ?)
35+ }
36+
2937 fn recv_into_buf ( & mut self ) -> Result < bool , io:: Error > {
3038 match self . socket . recv ( & mut self . buf ) {
3139 Ok ( size) => {
@@ -63,34 +71,48 @@ impl MidiLiveUdp {
6371 }
6472 }
6573
66- pub fn channel (
67- mut self ,
68- channel : u8 ,
69- ) -> Sig < impl SigT < Item = MidiMessages > > {
70- Sig :: from_buf_fn ( move |ctx, buf : & mut Vec < MidiMessages > | {
71- // This is called once per frame (not once per sample). This will add an imperceptible
72- // amount of latency (unless the output buffer is too large!), but reduce cpu usage.
73- buf. resize_with ( ctx. num_samples , Default :: default) ;
74- let mut midi_messages = MidiMessages :: empty ( ) ;
75- loop {
76- match self . recv_midi_event ( ) {
77- Err ( e) => {
78- log:: warn!( "IO error reading from UDP socket: {e}" ) ;
79- break ;
80- }
81- Ok ( None ) => break ,
82- Ok ( Some ( MidiEvent {
83- channel : message_channel,
84- message,
85- } ) ) => {
86- if message_channel == channel {
87- midi_messages. push ( message) ;
88- }
74+ pub fn channel ( self , channel : u8 ) -> Sig < MidiLiveUdpChannel > {
75+ Sig ( MidiLiveUdpChannel {
76+ channel : channel. into ( ) ,
77+ server : self ,
78+ buf : Vec :: new ( ) ,
79+ } )
80+ }
81+ }
82+
83+ pub struct MidiLiveUdpChannel {
84+ pub channel : u4 ,
85+ pub server : MidiLiveUdp ,
86+ buf : Vec < MidiMessages > ,
87+ }
88+
89+ impl SigT for MidiLiveUdpChannel {
90+ type Item = MidiMessages ;
91+
92+ fn sample ( & mut self , ctx : & SigCtx ) -> impl Buf < Self :: Item > {
93+ // This is called once per frame (not once per sample). This will add an imperceptible
94+ // amount of latency (unless the output buffer is too large!), but reduce cpu usage.
95+ self . buf . resize_with ( ctx. num_samples , Default :: default) ;
96+ let mut midi_messages = MidiMessages :: empty ( ) ;
97+ loop {
98+ match self . server . recv_midi_event ( ) {
99+ Err ( e) => {
100+ log:: warn!( "IO error reading from UDP socket: {e}" ) ;
101+ break ;
102+ }
103+ Ok ( None ) => break ,
104+ Ok ( Some ( MidiEvent {
105+ channel : message_channel,
106+ message,
107+ } ) ) => {
108+ if message_channel == self . channel {
109+ midi_messages. push ( message) ;
89110 }
90111 }
91112 }
92- // Only the first sample of each frame is populated with midi messages.
93- buf[ 0 ] = midi_messages;
94- } )
113+ }
114+ // Only the first sample of each frame is populated with midi messages.
115+ self . buf [ 0 ] = midi_messages;
116+ & self . buf
95117 }
96118}
0 commit comments