1//! MIDI sequencer I/O and enumeration
2
3use libc::{c_uint, c_int, c_short, c_uchar, c_void, c_long, size_t, pollfd};
4use super::error::*;
5use crate::alsa;
6use super::{Direction, poll};
7use std::{ptr, fmt, mem, slice, time, cell};
8use std::str::{FromStr, Split};
9use std::ffi::CStr;
10use std::borrow::Cow;
11
12// Workaround for improper alignment of snd_seq_ev_ext_t in alsa-sys
13#[repr(packed)]
14struct EvExtPacked {
15 len: c_uint,
16 ptr: *mut c_void,
17}
18
19/// [snd_seq_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___sequencer.html) wrapper
20///
21/// To access the functions `event_input`, `event_input_pending` and `set_input_buffer_size`,
22/// you first have to obtain an instance of `Input` by calling `input()`. Only one instance of
23/// `Input` may exist at any time for a given `Seq`.
24pub struct Seq(*mut alsa::snd_seq_t, cell::Cell<bool>);
25
26unsafe impl Send for Seq {}
27
28impl Drop for Seq {
29 fn drop(&mut self) { unsafe { alsa::snd_seq_close(self.0) }; }
30}
31
32impl Seq {
33 fn check_has_input(&self) {
34 if self.1.get() { panic!("No additional Input object allowed")}
35 }
36
37 /// Opens the sequencer.
38 ///
39 /// If name is None, "default" will be used. That's almost always what you usually want to use anyway.
40 pub fn open(name: Option<&CStr>, dir: Option<Direction>, nonblock: bool) -> Result<Seq> {
41 let n2 = name.unwrap_or(unsafe { CStr::from_bytes_with_nul_unchecked(b"default\0") });
42 let mut h = ptr::null_mut();
43 let mode = if nonblock { alsa::SND_SEQ_NONBLOCK } else { 0 };
44 let streams = match dir {
45 None => alsa::SND_SEQ_OPEN_DUPLEX,
46 Some(Direction::Playback) => alsa::SND_SEQ_OPEN_OUTPUT,
47 Some(Direction::Capture) => alsa::SND_SEQ_OPEN_INPUT,
48 };
49 acheck!(snd_seq_open(&mut h, n2.as_ptr(), streams, mode))
50 .map(|_| Seq(h, cell::Cell::new(false)))
51 }
52
53 pub fn set_client_name(&self, name: &CStr) -> Result<()> {
54 acheck!(snd_seq_set_client_name(self.0, name.as_ptr())).map(|_| ())
55 }
56
57 pub fn set_client_event_filter(&self, event_type: i32) -> Result<()> {
58 acheck!(snd_seq_set_client_event_filter(self.0, event_type as c_int)).map(|_| ())
59 }
60
61 pub fn set_client_pool_output(&self, size: u32) -> Result<()> {
62 acheck!(snd_seq_set_client_pool_output(self.0, size as size_t)).map(|_| ())
63 }
64
65 pub fn set_client_pool_input(&self, size: u32) -> Result<()> {
66 acheck!(snd_seq_set_client_pool_input(self.0, size as size_t)).map(|_| ())
67 }
68
69 pub fn set_client_pool_output_room(&self, size: u32) -> Result<()> {
70 acheck!(snd_seq_set_client_pool_output_room(self.0, size as size_t)).map(|_| ())
71 }
72
73 pub fn client_id(&self) -> Result<i32> {
74 acheck!(snd_seq_client_id(self.0)).map(|q| q as i32)
75 }
76
77 pub fn drain_output(&self) -> Result<i32> {
78 acheck!(snd_seq_drain_output(self.0)).map(|q| q as i32)
79 }
80
81 pub fn get_any_client_info(&self, client: i32) -> Result<ClientInfo> {
82 let c = ClientInfo::new()?;
83 acheck!(snd_seq_get_any_client_info(self.0, client, c.0)).map(|_| c)
84 }
85
86 pub fn get_any_port_info(&self, a: Addr) -> Result<PortInfo> {
87 let c = PortInfo::new()?;
88 acheck!(snd_seq_get_any_port_info(self.0, a.client as c_int, a.port as c_int, c.0)).map(|_| c)
89 }
90
91 pub fn create_port(&self, port: &PortInfo) -> Result<()> {
92 acheck!(snd_seq_create_port(self.0, port.0)).map(|_| ())
93 }
94
95 pub fn create_simple_port(&self, name: &CStr, caps: PortCap, t: PortType) -> Result<i32> {
96 acheck!(snd_seq_create_simple_port(self.0, name.as_ptr(), caps.bits() as c_uint, t.bits() as c_uint)).map(|q| q as i32)
97 }
98
99 pub fn set_port_info(&self, port: i32, info: &mut PortInfo) -> Result<()> {
100 acheck!(snd_seq_set_port_info(self.0, port, info.0)).map(|_| ())
101 }
102
103 pub fn delete_port(&self, port: i32) -> Result<()> {
104 acheck!(snd_seq_delete_port(self.0, port as c_int)).map(|_| ())
105 }
106
107 pub fn subscribe_port(&self, info: &PortSubscribe) -> Result<()> {
108 acheck!(snd_seq_subscribe_port(self.0, info.0)).map(|_| ())
109 }
110
111 pub fn unsubscribe_port(&self, sender: Addr, dest: Addr) -> Result<()> {
112 let z = PortSubscribe::new()?;
113 z.set_sender(sender);
114 z.set_dest(dest);
115 acheck!(snd_seq_unsubscribe_port(self.0, z.0)).map(|_| ())
116 }
117
118 pub fn control_queue(&self, q: i32, t: EventType, value: i32, e: Option<&mut Event>) -> Result<()> {
119 assert!(EvQueueControl::<()>::has_data(t) || EvQueueControl::<i32>::has_data(t) || EvQueueControl::<u32>::has_data(t));
120 let p = e.map(|e| &mut e.0 as *mut _).unwrap_or(ptr::null_mut());
121 acheck!(snd_seq_control_queue(self.0, q as c_int, t as c_int, value as c_int, p)).map(|_| ())
122 }
123
124 pub fn event_output(&self, e: &mut Event) -> Result<u32> {
125 e.ensure_buf();
126 acheck!(snd_seq_event_output(self.0, &mut e.0)).map(|q| q as u32)
127 }
128
129 pub fn event_output_buffer(&self, e: &mut Event) -> Result<u32> {
130 e.ensure_buf();
131 acheck!(snd_seq_event_output_buffer(self.0, &mut e.0)).map(|q| q as u32)
132 }
133
134 pub fn event_output_direct(&self, e: &mut Event) -> Result<u32> {
135 e.ensure_buf();
136 acheck!(snd_seq_event_output_direct(self.0, &mut e.0)).map(|q| q as u32)
137 }
138
139 pub fn get_queue_tempo(&self, q: i32) -> Result<QueueTempo> {
140 let value = QueueTempo::new()?;
141 acheck!(snd_seq_get_queue_tempo(self.0, q as c_int, value.0)).map(|_| value)
142 }
143
144 pub fn set_queue_tempo(&self, q: i32, value: &QueueTempo) -> Result<()> {
145 acheck!(snd_seq_set_queue_tempo(self.0, q as c_int, value.0)).map(|_| ())
146 }
147
148 pub fn get_queue_status(&self, q: i32) -> Result<QueueStatus> {
149 let value = QueueStatus::new()?;
150 acheck!(snd_seq_get_queue_status(self.0, q as c_int, value.0)).map(|_| value)
151 }
152
153 pub fn free_queue(&self, q: i32) -> Result<()> { acheck!(snd_seq_free_queue(self.0, q)).map(|_| ()) }
154 pub fn alloc_queue(&self) -> Result<i32> { acheck!(snd_seq_alloc_queue(self.0)).map(|q| q as i32) }
155 pub fn alloc_named_queue(&self, n: &CStr) -> Result<i32> {
156 acheck!(snd_seq_alloc_named_queue(self.0, n.as_ptr())).map(|q| q as i32)
157 }
158
159 pub fn sync_output_queue(&self) -> Result<()> {
160 acheck!(snd_seq_sync_output_queue(self.0)).map(|_| ())
161 }
162
163 pub fn drop_output(&self) -> Result<()> {
164 acheck!(snd_seq_drop_output(self.0)).map(|_| ())
165 }
166
167 /// Call this function to obtain an instance of `Input` to access the functions `event_input`,
168 /// `event_input_pending` and `set_input_buffer_size`. See the documentation of `Input` for details.
169 pub fn input(&self) -> Input {
170 Input::new(self)
171 }
172
173 pub fn remove_events(&self, condition: RemoveEvents) -> Result<()> {
174 acheck!(snd_seq_remove_events(self.0, condition.0)).map(|_| ())
175 }
176}
177
178/// Struct for receiving input events from a sequencer. The methods offered by this
179/// object may modify the internal input buffer of the sequencer, which must not happen
180/// while an `Event` is alive that has been obtained from a call to `event_input` (which
181/// takes `Input` by mutable reference for this reason). This is because the event might
182/// directly reference the sequencer's input buffer for variable-length messages (e.g. Sysex).
183///
184/// Note: Only one `Input` object is allowed in scope at a time.
185pub struct Input<'a>(&'a Seq);
186
187impl<'a> Drop for Input<'a> {
188 fn drop(&mut self) { (self.0).1.set(val:false) }
189}
190
191impl<'a> Input<'a> {
192 fn new(s: &'a Seq) -> Input<'a> {
193 s.check_has_input();
194 s.1.set(true);
195 Input(s)
196 }
197
198 pub fn event_input(&mut self) -> Result<Event> {
199 // The returned event might reference the input buffer of the `Seq`.
200 // Therefore we mutably borrow the `Input` structure, preventing any
201 // other function call that might change the input buffer while the
202 // event is alive.
203 let mut z = ptr::null_mut();
204 acheck!(snd_seq_event_input((self.0).0, &mut z))?;
205 unsafe { Event::extract (&mut *z, "snd_seq_event_input") }
206 }
207
208 pub fn event_input_pending(&self, fetch_sequencer: bool) -> Result<u32> {
209 acheck!(snd_seq_event_input_pending((self.0).0, if fetch_sequencer {1} else {0})).map(|q| q as u32)
210 }
211
212 pub fn set_input_buffer_size(&self, size: u32) -> Result<()> {
213 acheck!(snd_seq_set_input_buffer_size((self.0).0, size as size_t)).map(|_| ())
214 }
215
216 pub fn drop_input(&self) -> Result<()> {
217 acheck!(snd_seq_drop_input((self.0).0)).map(|_| ())
218 }
219}
220
221fn polldir(o: Option<Direction>) -> c_short {
222 match o {
223 None => poll::Flags::IN | poll::Flags::OUT,
224 Some(Direction::Playback) => poll::Flags::OUT,
225 Some(Direction::Capture) => poll::Flags::IN,
226 }.bits()
227}
228
229impl<'a> poll::Descriptors for (&'a Seq, Option<Direction>) {
230
231 fn count(&self) -> usize {
232 unsafe { alsa::snd_seq_poll_descriptors_count((self.0).0, events:polldir(self.1)) as usize }
233 }
234
235 fn fill(&self, p: &mut [pollfd]) -> Result<usize> {
236 let z: i32 = unsafe { alsa::snd_seq_poll_descriptors((self.0).0, pfds:p.as_mut_ptr(), space:p.len() as c_uint, events:polldir(self.1)) };
237 from_code("snd_seq_poll_descriptors", z).map(|_| z as usize)
238 }
239
240 fn revents(&self, p: &[pollfd]) -> Result<poll::Flags> {
241 let mut r: u16 = 0;
242 let z: i32 = unsafe { alsa::snd_seq_poll_descriptors_revents((self.0).0, pfds:p.as_ptr() as *mut pollfd, nfds:p.len() as c_uint, &mut r) };
243 from_code("snd_seq_poll_descriptors_revents", z).map(|_| poll::Flags::from_bits_truncate(bits:r as c_short))
244 }
245}
246
247/// [snd_seq_client_info_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_client.html) wrapper
248pub struct ClientInfo(*mut alsa::snd_seq_client_info_t);
249
250unsafe impl Send for ClientInfo {}
251
252impl Drop for ClientInfo {
253 fn drop(&mut self) {
254 unsafe { alsa::snd_seq_client_info_free(self.0) };
255 }
256}
257
258impl ClientInfo {
259 fn new() -> Result<Self> {
260 let mut p: *mut _snd_seq_client_info = ptr::null_mut();
261 acheck!(snd_seq_client_info_malloc(&mut p)).map(|_| ClientInfo(p))
262 }
263
264 // Not sure if it's useful for this one to be public.
265 fn set_client(&self, client: i32) {
266 unsafe { alsa::snd_seq_client_info_set_client(self.0, client as c_int) };
267 }
268
269 pub fn get_client(&self) -> i32 {
270 unsafe { alsa::snd_seq_client_info_get_client(self.0) as i32 }
271 }
272
273 pub fn get_name(&self) -> Result<&str> {
274 let c: *const i8 = unsafe { alsa::snd_seq_client_info_get_name(self.0) };
275 from_const(func:"snd_seq_client_info_get_name", s:c)
276 }
277}
278
279impl fmt::Debug for ClientInfo {
280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
281 write!(f, "ClientInfo({},{:?})", self.get_client(), self.get_name())
282 }
283}
284
285#[derive(Copy, Clone)]
286/// Iterates over clients connected to the seq API (both kernel and userspace clients).
287pub struct ClientIter<'a>(&'a Seq, i32);
288
289impl<'a> ClientIter<'a> {
290 pub fn new(seq: &'a Seq) -> Self { ClientIter(seq, -1) }
291}
292
293impl<'a> Iterator for ClientIter<'a> {
294 type Item = ClientInfo;
295 fn next(&mut self) -> Option<Self::Item> {
296 let z: ClientInfo = ClientInfo::new().unwrap();
297 z.set_client(self.1);
298 let r: i32 = unsafe { alsa::snd_seq_query_next_client((self.0).0, info:z.0) };
299 if r < 0 { self.1 = -1; return None };
300 self.1 = z.get_client();
301 Some(z)
302 }
303}
304
305/// [snd_seq_port_info_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html) wrapper
306pub struct PortInfo(*mut alsa::snd_seq_port_info_t);
307
308unsafe impl Send for PortInfo {}
309
310impl Drop for PortInfo {
311 fn drop(&mut self) {
312 unsafe { alsa::snd_seq_port_info_free(self.0) };
313 }
314}
315
316impl PortInfo {
317 fn new() -> Result<Self> {
318 let mut p = ptr::null_mut();
319 acheck!(snd_seq_port_info_malloc(&mut p)).map(|_| PortInfo(p))
320 }
321
322 /// Creates a new PortInfo with all fields set to zero.
323 pub fn empty() -> Result<Self> {
324 let z = Self::new()?;
325 unsafe { ptr::write_bytes(z.0 as *mut u8, 0, alsa::snd_seq_port_info_sizeof()) };
326 Ok(z)
327 }
328
329 pub fn get_client(&self) -> i32 {
330 unsafe { alsa::snd_seq_port_info_get_client(self.0) as i32 }
331 }
332
333 pub fn get_port(&self) -> i32 {
334 unsafe { alsa::snd_seq_port_info_get_port(self.0) as i32 }
335 }
336
337 // Not sure if it's useful for this one to be public.
338 fn set_client(&self, client: i32) {
339 unsafe { alsa::snd_seq_port_info_set_client(self.0, client as c_int) };
340 }
341
342 // Not sure if it's useful for this one to be public.
343 fn set_port(&self, port: i32) {
344 unsafe { alsa::snd_seq_port_info_set_port(self.0, port as c_int) };
345 }
346
347 pub fn get_name(&self) -> Result<&str> {
348 let c = unsafe { alsa::snd_seq_port_info_get_name(self.0) };
349 from_const("snd_seq_port_info_get_name", c)
350 }
351
352 pub fn set_name(&mut self, name: &CStr) {
353 // Note: get_name returns an interior reference, so this one must take &mut self
354 unsafe { alsa::snd_seq_port_info_set_name(self.0, name.as_ptr()) };
355 }
356
357 pub fn get_capability(&self) -> PortCap {
358 PortCap::from_bits_truncate(unsafe { alsa::snd_seq_port_info_get_capability(self.0) as u32 })
359 }
360
361 pub fn get_type(&self) -> PortType {
362 PortType::from_bits_truncate(unsafe { alsa::snd_seq_port_info_get_type(self.0) as u32 })
363 }
364
365 pub fn set_capability(&self, c: PortCap) {
366 unsafe { alsa::snd_seq_port_info_set_capability(self.0, c.bits() as c_uint) }
367 }
368
369 pub fn set_type(&self, c: PortType) {
370 unsafe { alsa::snd_seq_port_info_set_type(self.0, c.bits() as c_uint) }
371 }
372
373 /// Returns an Addr containing this PortInfo's client and port id.
374 pub fn addr(&self) -> Addr {
375 Addr {
376 client: self.get_client(),
377 port: self.get_port(),
378 }
379 }
380
381 pub fn get_midi_channels(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_midi_channels(self.0) as i32 } }
382 pub fn get_midi_voices(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_midi_voices(self.0) as i32 } }
383 pub fn get_synth_voices(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_synth_voices(self.0) as i32 } }
384 pub fn get_read_use(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_read_use(self.0) as i32 } }
385 pub fn get_write_use(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_write_use(self.0) as i32 } }
386 pub fn get_port_specified(&self) -> bool { unsafe { alsa::snd_seq_port_info_get_port_specified(self.0) == 1 } }
387 pub fn get_timestamping(&self) -> bool { unsafe { alsa::snd_seq_port_info_get_timestamping(self.0) == 1 } }
388 pub fn get_timestamp_real(&self) -> bool { unsafe { alsa::snd_seq_port_info_get_timestamp_real(self.0) == 1 } }
389 pub fn get_timestamp_queue(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_timestamp_queue(self.0) as i32 } }
390
391 pub fn set_midi_channels(&self, value: i32) { unsafe { alsa::snd_seq_port_info_set_midi_channels(self.0, value as c_int) } }
392 pub fn set_midi_voices(&self, value: i32) { unsafe { alsa::snd_seq_port_info_set_midi_voices(self.0, value as c_int) } }
393 pub fn set_synth_voices(&self, value: i32) { unsafe { alsa::snd_seq_port_info_set_synth_voices(self.0, value as c_int) } }
394 pub fn set_port_specified(&self, value: bool) { unsafe { alsa::snd_seq_port_info_set_port_specified(self.0, if value { 1 } else { 0 } ) } }
395 pub fn set_timestamping(&self, value: bool) { unsafe { alsa::snd_seq_port_info_set_timestamping(self.0, if value { 1 } else { 0 } ) } }
396 pub fn set_timestamp_real(&self, value: bool) { unsafe { alsa::snd_seq_port_info_set_timestamp_real(self.0, if value { 1 } else { 0 } ) } }
397 pub fn set_timestamp_queue(&self, value: i32) { unsafe { alsa::snd_seq_port_info_set_timestamp_queue(self.0, value as c_int) } }
398}
399
400impl fmt::Debug for PortInfo {
401 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
402 write!(f, "PortInfo({}:{},{:?})", self.get_client(), self.get_port(), self.get_name())
403 }
404}
405
406#[derive(Copy, Clone)]
407/// Iterates over clients connected to the seq API (both kernel and userspace clients).
408pub struct PortIter<'a>(&'a Seq, i32, i32);
409
410impl<'a> PortIter<'a> {
411 pub fn new(seq: &'a Seq, client: i32) -> Self { PortIter(seq, client, -1) }
412}
413
414impl<'a> Iterator for PortIter<'a> {
415 type Item = PortInfo;
416 fn next(&mut self) -> Option<Self::Item> {
417 let z: PortInfo = PortInfo::new().unwrap();
418 z.set_client(self.1);
419 z.set_port(self.2);
420 let r: i32 = unsafe { alsa::snd_seq_query_next_port((self.0).0, info:z.0) };
421 if r < 0 { self.2 = -1; return None };
422 self.2 = z.get_port();
423 Some(z)
424 }
425}
426
427bitflags! {
428 #[repr(transparent)]
429 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
430 /// [SND_SEQ_PORT_CAP_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html) constants
431 pub struct PortCap: u32 {
432 const READ = 1<<0;
433 const WRITE = 1<<1;
434 const SYNC_READ = 1<<2;
435 const SYNC_WRITE = 1<<3;
436 const DUPLEX = 1<<4;
437 const SUBS_READ = 1<<5;
438 const SUBS_WRITE = 1<<6;
439 const NO_EXPORT = 1<<7;
440 }
441}
442
443bitflags! {
444 #[repr(transparent)]
445 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
446 /// [SND_SEQ_PORT_TYPE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html) constants
447 pub struct PortType: u32 {
448 const SPECIFIC = (1<<0);
449 const MIDI_GENERIC = (1<<1);
450 const MIDI_GM = (1<<2);
451 const MIDI_GS = (1<<3);
452 const MIDI_XG = (1<<4);
453 const MIDI_MT32 = (1<<5);
454 const MIDI_GM2 = (1<<6);
455 const SYNTH = (1<<10);
456 const DIRECT_SAMPLE = (1<<11);
457 const SAMPLE = (1<<12);
458 const HARDWARE = (1<<16);
459 const SOFTWARE = (1<<17);
460 const SYNTHESIZER = (1<<18);
461 const PORT = (1<<19);
462 const APPLICATION = (1<<20);
463 }
464}
465
466bitflags! {
467 #[repr(transparent)]
468 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
469 /// [SND_SEQ_REMOVE_xxx](https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_event.html) constants
470 pub struct Remove: u32 {
471 const INPUT = (1<<0);
472 const OUTPUT = (1<<1);
473 const DEST = (1<<2);
474 const DEST_CHANNEL = (1<<3);
475 const TIME_BEFORE = (1<<4);
476 const TIME_AFTER = (1<<5);
477 const TIME_TICK = (1<<6);
478 const EVENT_TYPE = (1<<7);
479 const IGNORE_OFF = (1<<8);
480 const TAG_MATCH = (1<<9);
481 }
482}
483
484
485/// [snd_seq_addr_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__addr__t.html) wrapper
486#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
487pub struct Addr {
488 pub client: i32,
489 pub port: i32,
490}
491
492impl FromStr for Addr {
493 type Err = Box<dyn std::error::Error>;
494
495 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
496 let mut split: Split<'_, char> = s.trim().split(':');
497 let client: i32 = split&str.next()
498 .ok_or(err:"no client provided")?
499 .parse::<i32>()?;
500 let port: i32 = split&str.next()
501 .ok_or(err:"no port provided")?
502 .parse::<i32>()?;
503 match split.next() {
504 Some(_) => {
505 Err("too many arguments".into())
506 },
507 None => {
508 Ok(Addr { client, port })
509 }
510 }
511 }
512}
513
514impl Addr {
515 pub fn system_timer() -> Addr { Addr { client: alsa::SND_SEQ_CLIENT_SYSTEM as i32, port: alsa::SND_SEQ_PORT_SYSTEM_TIMER as i32 } }
516 pub fn system_announce() -> Addr { Addr { client: alsa::SND_SEQ_CLIENT_SYSTEM as i32, port: alsa::SND_SEQ_PORT_SYSTEM_ANNOUNCE as i32 } }
517 pub fn broadcast() -> Addr { Addr { client: alsa::SND_SEQ_ADDRESS_BROADCAST as i32, port: alsa::SND_SEQ_ADDRESS_BROADCAST as i32 } }
518}
519
520/// [snd_seq_port_subscribe_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html) wrapper
521pub struct PortSubscribe(*mut alsa::snd_seq_port_subscribe_t);
522
523unsafe impl Send for PortSubscribe {}
524
525impl Drop for PortSubscribe {
526 fn drop(&mut self) { unsafe { alsa::snd_seq_port_subscribe_free(self.0) }; }
527}
528
529impl PortSubscribe {
530 fn new() -> Result<Self> {
531 let mut p = ptr::null_mut();
532 acheck!(snd_seq_port_subscribe_malloc(&mut p)).map(|_| PortSubscribe(p))
533 }
534
535 /// Creates a new PortSubscribe with all fields set to zero.
536 pub fn empty() -> Result<Self> {
537 let z = Self::new()?;
538 unsafe { ptr::write_bytes(z.0 as *mut u8, 0, alsa::snd_seq_port_subscribe_sizeof()) };
539 Ok(z)
540 }
541
542 pub fn get_sender(&self) -> Addr { unsafe {
543 let z = alsa::snd_seq_port_subscribe_get_sender(self.0);
544 Addr { client: (*z).client as i32, port: (*z).port as i32 }
545 } }
546
547 pub fn get_dest(&self) -> Addr { unsafe {
548 let z = alsa::snd_seq_port_subscribe_get_dest(self.0);
549 Addr { client: (*z).client as i32, port: (*z).port as i32 }
550 } }
551
552 pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_port_subscribe_get_queue(self.0) as i32 } }
553 pub fn get_exclusive(&self) -> bool { unsafe { alsa::snd_seq_port_subscribe_get_exclusive(self.0) == 1 } }
554 pub fn get_time_update(&self) -> bool { unsafe { alsa::snd_seq_port_subscribe_get_time_update(self.0) == 1 } }
555 pub fn get_time_real(&self) -> bool { unsafe { alsa::snd_seq_port_subscribe_get_time_real(self.0) == 1 } }
556
557 pub fn set_sender(&self, value: Addr) {
558 let z = alsa::snd_seq_addr_t { client: value.client as c_uchar, port: value.port as c_uchar };
559 unsafe { alsa::snd_seq_port_subscribe_set_sender(self.0, &z) };
560 }
561
562 pub fn set_dest(&self, value: Addr) {
563 let z = alsa::snd_seq_addr_t { client: value.client as c_uchar, port: value.port as c_uchar };
564 unsafe { alsa::snd_seq_port_subscribe_set_dest(self.0, &z) };
565 }
566
567 pub fn set_queue(&self, value: i32) { unsafe { alsa::snd_seq_port_subscribe_set_queue(self.0, value as c_int) } }
568 pub fn set_exclusive(&self, value: bool) { unsafe { alsa::snd_seq_port_subscribe_set_exclusive(self.0, if value { 1 } else { 0 } ) } }
569 pub fn set_time_update(&self, value: bool) { unsafe { alsa::snd_seq_port_subscribe_set_time_update(self.0, if value { 1 } else { 0 } ) } }
570 pub fn set_time_real(&self, value: bool) { unsafe { alsa::snd_seq_port_subscribe_set_time_real(self.0, if value { 1 } else { 0 } ) } }
571
572}
573
574/// [snd_seq_query_subs_type_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html) wrapper
575#[derive(Copy, Clone)]
576pub enum QuerySubsType {
577 READ = alsa::SND_SEQ_QUERY_SUBS_READ as isize,
578 WRITE = alsa::SND_SEQ_QUERY_SUBS_WRITE as isize,
579}
580
581/// [snd_seq_query_subscribe_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html) wrapper
582//(kept private, functionality exposed by PortSubscribeIter)
583struct QuerySubscribe(*mut alsa::snd_seq_query_subscribe_t);
584
585unsafe impl Send for QuerySubscribe {}
586
587impl Drop for QuerySubscribe {
588 fn drop(&mut self) { unsafe { alsa::snd_seq_query_subscribe_free(self.0) } }
589}
590
591impl QuerySubscribe {
592 pub fn new() -> Result<Self> {
593 let mut q = ptr::null_mut();
594 acheck!(snd_seq_query_subscribe_malloc(&mut q)).map(|_| QuerySubscribe(q))
595 }
596
597 pub fn get_index(&self) -> i32 { unsafe { alsa::snd_seq_query_subscribe_get_index(self.0) as i32 } }
598 pub fn get_addr(&self) -> Addr { unsafe {
599 let a = &(*alsa::snd_seq_query_subscribe_get_addr(self.0));
600 Addr { client: a.client as i32, port: a.port as i32 }
601 } }
602 pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_query_subscribe_get_queue(self.0) as i32 } }
603 pub fn get_exclusive(&self) -> bool { unsafe { alsa::snd_seq_query_subscribe_get_exclusive(self.0) == 1 } }
604 pub fn get_time_update(&self) -> bool { unsafe { alsa::snd_seq_query_subscribe_get_time_update(self.0) == 1 } }
605 pub fn get_time_real(&self) -> bool { unsafe { alsa::snd_seq_query_subscribe_get_time_real(self.0) == 1 } }
606
607 pub fn set_root(&self, value: Addr) { unsafe {
608 let a = alsa::snd_seq_addr_t { client: value.client as c_uchar, port: value.port as c_uchar};
609 alsa::snd_seq_query_subscribe_set_root(self.0, &a);
610 } }
611 pub fn set_type(&self, value: QuerySubsType) { unsafe {
612 alsa::snd_seq_query_subscribe_set_type(self.0, value as alsa::snd_seq_query_subs_type_t)
613 } }
614 pub fn set_index(&self, value: i32) { unsafe { alsa::snd_seq_query_subscribe_set_index(self.0, value as c_int) } }
615}
616
617#[derive(Copy, Clone)]
618/// Iterates over port subscriptions for a given client:port/type.
619pub struct PortSubscribeIter<'a> {
620 seq: &'a Seq,
621 addr: Addr,
622 query_subs_type: QuerySubsType,
623 index: i32
624}
625
626impl<'a> PortSubscribeIter<'a> {
627 pub fn new(seq: &'a Seq, addr: Addr, query_subs_type: QuerySubsType) -> Self {
628 PortSubscribeIter {seq, addr, query_subs_type, index: 0 }
629 }
630}
631
632impl<'a> Iterator for PortSubscribeIter<'a> {
633 type Item = PortSubscribe;
634
635 fn next(&mut self) -> Option<Self::Item> {
636 let query = QuerySubscribe::new().unwrap();
637
638 query.set_root(self.addr);
639 query.set_type(self.query_subs_type);
640 query.set_index(self.index);
641
642 let r = unsafe { alsa::snd_seq_query_port_subscribers((self.seq).0, query.0) };
643 if r < 0 {
644 self.index = 0;
645 return None;
646 }
647
648 self.index = query.get_index() + 1;
649 let vtr = PortSubscribe::new().unwrap();
650 match self.query_subs_type {
651 QuerySubsType::READ => {
652 vtr.set_sender(self.addr);
653 vtr.set_dest(query.get_addr());
654 },
655 QuerySubsType:: WRITE => {
656 vtr.set_sender(query.get_addr());
657 vtr.set_dest(self.addr);
658 }
659 };
660 vtr.set_queue(query.get_queue());
661 vtr.set_exclusive(query.get_exclusive());
662 vtr.set_time_update(query.get_time_update());
663 vtr.set_time_real(query.get_time_real());
664
665 Some(vtr)
666 }
667}
668
669/// [snd_seq_event_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html) wrapper
670///
671/// Fields of the event is not directly exposed. Instead call `Event::new` to set data (which can be, e g, an EvNote).
672/// Use `get_type` and `get_data` to retrieve data.
673///
674/// The lifetime parameter refers to the lifetime of an associated external buffer that might be used for
675/// variable-length messages (e.g. SysEx).
676pub struct Event<'a>(alsa::snd_seq_event_t, EventType, Option<Cow<'a, [u8]>>);
677
678unsafe impl<'a> Send for Event<'a> {}
679
680impl<'a> Event<'a> {
681 /// Creates a new event. For events that carry variable-length data (e.g. Sysex), `new_ext` has to be used instead.
682 pub fn new<D: EventData>(t: EventType, data: &D) -> Event<'static> {
683 assert!(!Event::has_ext_data(t), "event type must not carry variable-length data");
684 let mut z = Event(unsafe { mem::zeroed() }, t, None);
685 (z.0).type_ = t as c_uchar;
686 (z.0).flags |= Event::get_length_flag(t);
687 debug_assert!(D::has_data(t));
688 data.set_data(&mut z);
689 z
690 }
691
692 /// Creates a new event carrying variable-length data. This is required for event types `Sysex`, `Bounce`, and the `UsrVar` types.
693 pub fn new_ext<D: Into<Cow<'a, [u8]>>>(t: EventType, data: D) -> Event<'a> {
694 assert!(Event::has_ext_data(t), "event type must carry variable-length data");
695 let mut z = Event(unsafe { mem::zeroed() }, t, Some(data.into()));
696 (z.0).type_ = t as c_uchar;
697 (z.0).flags |= Event::get_length_flag(t);
698 z
699 }
700
701 /// Consumes this event and returns an (otherwise unchanged) event where the externally referenced
702 /// buffer for variable length messages (e.g. SysEx) has been copied into the event.
703 /// The returned event has a static lifetime, i e, it's decoupled from the original buffer.
704 pub fn into_owned(self) -> Event<'static> {
705 Event(self.0, self.1, self.2.map(|cow| Cow::Owned(cow.into_owned())))
706 }
707
708 fn get_length_flag(t: EventType) -> u8 {
709 match t {
710 EventType::Sysex => alsa::SND_SEQ_EVENT_LENGTH_VARIABLE,
711 EventType::Bounce => alsa::SND_SEQ_EVENT_LENGTH_VARIABLE, // not clear whether this should be VARIABLE or VARUSR
712 EventType::UsrVar0 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR,
713 EventType::UsrVar1 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR,
714 EventType::UsrVar2 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR,
715 EventType::UsrVar3 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR,
716 EventType::UsrVar4 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR,
717 _ => alsa::SND_SEQ_EVENT_LENGTH_FIXED
718 }
719 }
720
721 fn has_ext_data(t: EventType) -> bool {
722 Event::get_length_flag(t) != alsa::SND_SEQ_EVENT_LENGTH_FIXED
723 }
724
725 /// Extracts event type and data. Produces a result with an arbitrary lifetime, hence the unsafety.
726 unsafe fn extract<'any>(z: &mut alsa::snd_seq_event_t, func: &'static str) -> Result<Event<'any>> {
727 let t = EventType::from_c_int((*z).type_ as c_int, func)?;
728 let ext_data = if Event::has_ext_data(t) {
729 assert_ne!((*z).flags & alsa::SND_SEQ_EVENT_LENGTH_MASK, alsa::SND_SEQ_EVENT_LENGTH_FIXED);
730 Some(Cow::Borrowed({
731 let zz: &EvExtPacked = &*(&(*z).data as *const alsa::snd_seq_event__bindgen_ty_1 as *const _);
732 slice::from_raw_parts((*zz).ptr as *mut u8, (*zz).len as usize)
733 }))
734 } else {
735 None
736 };
737 Ok(Event(ptr::read(z), t, ext_data))
738 }
739
740 /// Ensures that the ev.ext union element points to the correct resize_buffer for events
741 /// with variable length content
742 fn ensure_buf(&mut self) {
743 if !Event::has_ext_data(self.1) { return; }
744 let slice: &[u8] = match self.2 {
745 Some(Cow::Owned(ref mut vec)) => &vec[..],
746 Some(Cow::Borrowed(buf)) => buf,
747 // The following case is always a logic error in the program, thus panicking is okay.
748 None => panic!("event type requires variable-length data, but none was provided")
749 };
750 let z: &mut EvExtPacked = unsafe { &mut *(&mut self.0.data as *mut alsa::snd_seq_event__bindgen_ty_1 as *mut _) };
751 z.len = slice.len() as c_uint;
752 z.ptr = slice.as_ptr() as *mut c_void;
753 }
754
755 #[inline]
756 pub fn get_type(&self) -> EventType { self.1 }
757
758 /// Extract the event data from an event.
759 /// Use `get_ext` instead for events carrying variable-length data.
760 pub fn get_data<D: EventData>(&self) -> Option<D> { if D::has_data(self.1) { Some(D::get_data(self)) } else { None } }
761
762 /// Extract the variable-length data carried by events of type `Sysex`, `Bounce`, or the `UsrVar` types.
763 pub fn get_ext(&self) -> Option<&[u8]> {
764 if Event::has_ext_data(self.1) {
765 match self.2 {
766 Some(Cow::Owned(ref vec)) => Some(&vec[..]),
767 Some(Cow::Borrowed(buf)) => Some(buf),
768 // The following case is always a logic error in the program, thus panicking is okay.
769 None => panic!("event type requires variable-length data, but none was found")
770 }
771 } else {
772 None
773 }
774 }
775
776 pub fn set_subs(&mut self) {
777 self.0.dest.client = alsa::SND_SEQ_ADDRESS_SUBSCRIBERS;
778 self.0.dest.port = alsa::SND_SEQ_ADDRESS_UNKNOWN;
779 }
780
781 pub fn set_source(&mut self, p: i32) { self.0.source.port = p as u8 }
782 pub fn set_dest(&mut self, d: Addr) { self.0.dest.client = d.client as c_uchar; self.0.dest.port = d.port as c_uchar; }
783 pub fn set_tag(&mut self, t: u8) { self.0.tag = t as c_uchar; }
784 pub fn set_queue(&mut self, q: i32) { self.0.queue = q as c_uchar; }
785
786 pub fn get_source(&self) -> Addr { Addr { client: self.0.source.client as i32, port: self.0.source.port as i32 } }
787 pub fn get_dest(&self) -> Addr { Addr { client: self.0.dest.client as i32, port: self.0.dest.port as i32 } }
788 pub fn get_tag(&self) -> u8 { self.0.tag as u8 }
789 pub fn get_queue(&self) -> i32 { self.0.queue as i32 }
790
791 pub fn schedule_real(&mut self, queue: i32, relative: bool, rtime: time::Duration) {
792 self.0.flags &= !(alsa::SND_SEQ_TIME_STAMP_MASK | alsa::SND_SEQ_TIME_MODE_MASK);
793 self.0.flags |= alsa::SND_SEQ_TIME_STAMP_REAL | (if relative { alsa::SND_SEQ_TIME_MODE_REL } else { alsa::SND_SEQ_TIME_MODE_ABS });
794 self.0.queue = queue as u8;
795 let t = unsafe { &mut self.0.time.time };
796 t.tv_sec = rtime.as_secs() as c_uint;
797 t.tv_nsec = rtime.subsec_nanos() as c_uint;
798 }
799
800 pub fn schedule_tick(&mut self, queue: i32, relative: bool, ttime: u32) {
801 self.0.flags &= !(alsa::SND_SEQ_TIME_STAMP_MASK | alsa::SND_SEQ_TIME_MODE_MASK);
802 self.0.flags |= alsa::SND_SEQ_TIME_STAMP_TICK | (if relative { alsa::SND_SEQ_TIME_MODE_REL } else { alsa::SND_SEQ_TIME_MODE_ABS });
803 self.0.queue = queue as u8;
804 let t = unsafe { &mut self.0.time.tick };
805 *t = ttime as c_uint;
806 }
807
808 pub fn set_direct(&mut self) { self.0.queue = alsa::SND_SEQ_QUEUE_DIRECT }
809
810 pub fn get_relative(&self) -> bool { (self.0.flags & alsa::SND_SEQ_TIME_MODE_REL) != 0 }
811
812 pub fn get_time(&self) -> Option<time::Duration> {
813 if (self.0.flags & alsa::SND_SEQ_TIME_STAMP_REAL) != 0 {
814 let d = self.0.time;
815 let t = unsafe { &d.time };
816 Some(time::Duration::new(t.tv_sec as u64, t.tv_nsec as u32))
817 } else { None }
818 }
819
820 pub fn get_tick(&self) -> Option<u32> {
821 if (self.0.flags & alsa::SND_SEQ_TIME_STAMP_REAL) == 0 {
822 let d = self.0.time;
823 let t = unsafe { &d.tick };
824 Some(*t)
825 } else { None }
826 }
827
828 /// Returns true if the message is high priority.
829 pub fn get_priority(&self) -> bool { (self.0.flags & alsa::SND_SEQ_PRIORITY_HIGH) != 0 }
830
831 pub fn set_priority(&mut self, is_high_prio: bool) {
832 if is_high_prio { self.0.flags |= alsa::SND_SEQ_PRIORITY_HIGH; }
833 else { self.0.flags &= !alsa::SND_SEQ_PRIORITY_HIGH; }
834 }
835}
836
837impl<'a> Clone for Event<'a> {
838 fn clone(&self) -> Self { Event(unsafe { ptr::read(&self.0) }, self.1, self.2.clone()) }
839}
840
841impl<'a> fmt::Debug for Event<'a> {
842 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
843 let mut x: DebugTuple<'_, '_> = f.debug_tuple(name:"Event");
844 x.field(&self.1);
845 if let Some(z: EvNote) = self.get_data::<EvNote>() { x.field(&z); }
846 if let Some(z: EvCtrl) = self.get_data::<EvCtrl>() { x.field(&z); }
847 if let Some(z: Addr) = self.get_data::<Addr>() { x.field(&z); }
848 if let Some(z: Connect) = self.get_data::<Connect>() { x.field(&z); }
849 if let Some(z: EvQueueControl<()>) = self.get_data::<EvQueueControl<()>>() { x.field(&z); }
850 if let Some(z: EvQueueControl) = self.get_data::<EvQueueControl<i32>>() { x.field(&z); }
851 if let Some(z: EvQueueControl) = self.get_data::<EvQueueControl<u32>>() { x.field(&z); }
852 if let Some(z: EvQueueControl) = self.get_data::<EvQueueControl<time::Duration>>() { x.field(&z); }
853 if let Some(z: EvResult) = self.get_data::<EvResult>() { x.field(&z); }
854 if let Some(z: [u8; 12]) = self.get_data::<[u8; 12]>() { x.field(&z); }
855 if let Some(z: &[u8]) = self.get_ext() { x.field(&z); }
856 x.finish()
857 }
858}
859
860/// Internal trait implemented for different event type structs (`EvNote`, `EvCtrl`, etc).
861///
862/// Use it through `Event::get_data` and `Event::new`.
863pub trait EventData {
864 #[doc(hidden)]
865 fn get_data(ev: &Event) -> Self;
866 #[doc(hidden)]
867 fn has_data(e: EventType) -> bool;
868 #[doc(hidden)]
869 fn set_data(&self, ev: &mut Event);
870}
871
872impl EventData for () {
873 fn get_data(_: &Event) -> Self {}
874 fn has_data(e: EventType) -> bool {
875 matches!(e,
876 EventType::TuneRequest |
877 EventType::Reset |
878 EventType::Sensing |
879 EventType::None)
880 }
881 fn set_data(&self, _: &mut Event) {}
882}
883
884impl EventData for [u8; 12] {
885 fn get_data(ev: &Event) -> Self {
886 let d = unsafe { ptr::read(&ev.0.data) };
887 let z = unsafe { &d.raw8 };
888 z.d
889 }
890 fn has_data(e: EventType) -> bool {
891 matches!(e,
892 EventType::Echo |
893 EventType::Oss |
894 EventType::Usr0 |
895 EventType::Usr1 |
896 EventType::Usr2 |
897 EventType::Usr3 |
898 EventType::Usr4 |
899 EventType::Usr5 |
900 EventType::Usr6 |
901 EventType::Usr7 |
902 EventType::Usr8 |
903 EventType::Usr9)
904 }
905 fn set_data(&self, ev: &mut Event) {
906 let z = unsafe { &mut ev.0.data.raw8 };
907 z.d = *self;
908 }
909}
910
911
912#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
913pub struct EvNote {
914 pub channel: u8,
915 pub note: u8,
916 pub velocity: u8,
917 pub off_velocity: u8,
918 pub duration: u32,
919}
920
921impl EventData for EvNote {
922 fn get_data(ev: &Event) -> Self {
923 let z: &alsa::snd_seq_ev_note_t = unsafe { &*(&ev.0.data as *const alsa::snd_seq_event__bindgen_ty_1 as *const _) };
924 EvNote { channel: z.channel as u8, note: z.note as u8, velocity: z.velocity as u8, off_velocity: z.off_velocity as u8, duration: z.duration as u32 }
925 }
926 fn has_data(e: EventType) -> bool {
927 matches!(e,
928 EventType::Note |
929 EventType::Noteon |
930 EventType::Noteoff |
931 EventType::Keypress)
932 }
933 fn set_data(&self, ev: &mut Event) {
934 let z: &mut alsa::snd_seq_ev_note_t = unsafe { &mut *(&mut ev.0.data as *mut alsa::snd_seq_event__bindgen_ty_1 as *mut _) };
935 z.channel = self.channel as c_uchar;
936 z.note = self.note as c_uchar;
937 z.velocity = self.velocity as c_uchar;
938 z.off_velocity = self.off_velocity as c_uchar;
939 z.duration = self.duration as c_uint;
940 }
941}
942
943#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
944pub struct EvCtrl {
945 pub channel: u8,
946 pub param: u32,
947 pub value: i32,
948}
949
950impl EventData for EvCtrl {
951 fn get_data(ev: &Event) -> Self {
952 let z: &alsa::snd_seq_ev_ctrl_t = unsafe { &*(&ev.0.data as *const alsa::snd_seq_event__bindgen_ty_1 as *const _) };
953 EvCtrl { channel: z.channel as u8, param: z.param as u32, value: z.value as i32 }
954 }
955 fn has_data(e: EventType) -> bool {
956 matches!(e,
957 EventType::Controller |
958 EventType::Pgmchange |
959 EventType::Chanpress |
960 EventType::Pitchbend |
961 EventType::Control14 |
962 EventType::Nonregparam |
963 EventType::Regparam |
964 EventType::Songpos |
965 EventType::Songsel |
966 EventType::Qframe |
967 EventType::Timesign |
968 EventType::Keysign)
969 }
970 fn set_data(&self, ev: &mut Event) {
971 let z: &mut alsa::snd_seq_ev_ctrl_t = unsafe { &mut *(&mut ev.0.data as *mut alsa::snd_seq_event__bindgen_ty_1 as *mut _) };
972 z.channel = self.channel as c_uchar;
973 z.param = self.param as c_uint;
974 z.value = self.value as c_int;
975 }
976}
977
978impl EventData for Addr {
979 fn get_data(ev: &Event) -> Self {
980 let z: &alsa::snd_seq_addr_t = unsafe { &*(&ev.0.data as *const alsa::snd_seq_event__bindgen_ty_1 as *const _) };
981 Addr { client: z.client as i32, port: z.port as i32 }
982 }
983 fn has_data(e: EventType) -> bool {
984 matches!(e,
985 EventType::ClientStart |
986 EventType::ClientExit |
987 EventType::ClientChange |
988 EventType::PortStart |
989 EventType::PortExit |
990 EventType::PortChange)
991 }
992 fn set_data(&self, ev: &mut Event) {
993 let z: &mut alsa::snd_seq_addr_t = unsafe { &mut *(&mut ev.0.data as *mut alsa::snd_seq_event__bindgen_ty_1 as *mut _) };
994 z.client = self.client as c_uchar;
995 z.port = self.port as c_uchar;
996 }
997}
998
999#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
1000/// [snd_seq_connect_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__connect__t.html) wrapper
1001pub struct Connect {
1002 pub sender: Addr,
1003 pub dest: Addr,
1004}
1005
1006impl EventData for Connect {
1007 fn get_data(ev: &Event) -> Self {
1008 let d: snd_seq_event__bindgen_ty_1 = unsafe { ptr::read(&ev.0.data) };
1009 let z: &snd_seq_connect = unsafe { &d.connect };
1010 Connect {
1011 sender: Addr { client: z.sender.client as i32, port: z.sender.port as i32 },
1012 dest: Addr { client: z.dest.client as i32, port: z.dest.port as i32 }
1013 }
1014 }
1015 fn has_data(e: EventType) -> bool {
1016 matches!(e,
1017 EventType::PortSubscribed |
1018 EventType::PortUnsubscribed)
1019 }
1020 fn set_data(&self, ev: &mut Event) {
1021 let z: &mut snd_seq_connect = unsafe { &mut ev.0.data.connect };
1022 z.sender.client = self.sender.client as c_uchar;
1023 z.sender.port = self.sender.port as c_uchar;
1024 z.dest.client = self.dest.client as c_uchar;
1025 z.dest.port = self.dest.port as c_uchar;
1026 }
1027}
1028
1029#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
1030/// [snd_seq_ev_queue_control_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__ev__queue__control__t.html) wrapper
1031///
1032/// Note: This struct is generic, but what types of T are required for the different EvQueueControl messages is
1033/// not very well documented in alsa-lib. Right now, Tempo is i32, Tick, SetposTick and SyncPos are u32, SetposTime is time::Duration,
1034/// and the rest is (). If I guessed wrong, let me know.
1035pub struct EvQueueControl<T> {
1036 pub queue: i32,
1037 pub value: T,
1038}
1039
1040impl EventData for EvQueueControl<()> {
1041 fn get_data(ev: &Event) -> Self {
1042 let d: snd_seq_event__bindgen_ty_1 = unsafe { ptr::read(&ev.0.data) };
1043 let z: &snd_seq_ev_queue_control = unsafe { &d.queue };
1044 EvQueueControl { queue: z.queue as i32, value: () }
1045 }
1046 fn has_data(e: EventType) -> bool {
1047 matches!(e,
1048 EventType::Start |
1049 EventType::Continue |
1050 EventType::Stop |
1051 EventType::Clock |
1052 EventType::QueueSkew)
1053 }
1054 fn set_data(&self, ev: &mut Event) {
1055 let z: &mut snd_seq_ev_queue_control = unsafe { &mut ev.0.data.queue };
1056 z.queue = self.queue as c_uchar;
1057 }
1058}
1059
1060impl EventData for EvQueueControl<i32> {
1061 fn get_data(ev: &Event) -> Self { unsafe {
1062 let mut d: snd_seq_event__bindgen_ty_1 = ptr::read(&ev.0.data);
1063 let z: &mut snd_seq_ev_queue_control = &mut d.queue;
1064 EvQueueControl { queue: z.queue as i32, value: z.param.value as i32 }
1065 } }
1066 fn has_data(e: EventType) -> bool {
1067 matches!(e,
1068 EventType::Tempo)
1069 }
1070 fn set_data(&self, ev: &mut Event) { unsafe {
1071 let z: &mut snd_seq_ev_queue_control = &mut ev.0.data.queue;
1072 z.queue = self.queue as c_uchar;
1073 z.param.value = self.value as c_int;
1074 } }
1075}
1076
1077impl EventData for EvQueueControl<u32> {
1078 fn get_data(ev: &Event) -> Self { unsafe {
1079 let mut d: snd_seq_event__bindgen_ty_1 = ptr::read(&ev.0.data);
1080 let z: &mut snd_seq_ev_queue_control = &mut d.queue;
1081 EvQueueControl { queue: z.queue as i32, value: z.param.position as u32 }
1082 } }
1083 fn has_data(e: EventType) -> bool {
1084 matches!(e,
1085 EventType::SyncPos |
1086 EventType::Tick |
1087 EventType::SetposTick)
1088 }
1089 fn set_data(&self, ev: &mut Event) { unsafe {
1090 let z: &mut snd_seq_ev_queue_control = &mut ev.0.data.queue;
1091 z.queue = self.queue as c_uchar;
1092 z.param.position = self.value as c_uint;
1093 } }
1094}
1095
1096impl EventData for EvQueueControl<time::Duration> {
1097 fn get_data(ev: &Event) -> Self { unsafe {
1098 let mut d: snd_seq_event__bindgen_ty_1 = ptr::read(&ev.0.data);
1099 let z: &mut snd_seq_ev_queue_control = &mut d.queue;
1100 let t: &mut snd_seq_real_time = &mut z.param.time.time;
1101 EvQueueControl { queue: z.queue as i32, value: time::Duration::new(secs:t.tv_sec as u64, nanos:t.tv_nsec as u32) }
1102 } }
1103 fn has_data(e: EventType) -> bool {
1104 matches!(e,
1105 EventType::SetposTime)
1106 }
1107 fn set_data(&self, ev: &mut Event) { unsafe {
1108 let z: &mut snd_seq_ev_queue_control = &mut ev.0.data.queue;
1109 z.queue = self.queue as c_uchar;
1110 let t: &mut snd_seq_real_time = &mut z.param.time.time;
1111 t.tv_sec = self.value.as_secs() as c_uint;
1112 t.tv_nsec = self.value.subsec_nanos() as c_uint;
1113 } }
1114}
1115
1116#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
1117/// [snd_seq_result_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__result__t.html) wrapper
1118///
1119/// It's called EvResult instead of Result, in order to not be confused with Rust's Result type.
1120pub struct EvResult {
1121 pub event: i32,
1122 pub result: i32,
1123}
1124
1125impl EventData for EvResult {
1126 fn get_data(ev: &Event) -> Self {
1127 let d: snd_seq_event__bindgen_ty_1 = unsafe { ptr::read(&ev.0.data) };
1128 let z: &snd_seq_result = unsafe { &d.result };
1129 EvResult { event: z.event as i32, result: z.result as i32 }
1130 }
1131 fn has_data(e: EventType) -> bool {
1132 matches!(e,
1133 EventType::System |
1134 EventType::Result)
1135 }
1136 fn set_data(&self, ev: &mut Event) {
1137 let z: &mut snd_seq_result = unsafe { &mut ev.0.data.result };
1138 z.event = self.event as c_int;
1139 z.result = self.result as c_int;
1140 }
1141}
1142
1143
1144
1145alsa_enum!(
1146 /// [SND_SEQ_EVENT_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_events.html) constants
1147
1148 EventType, ALL_EVENT_TYPES[59],
1149
1150 Bounce = SND_SEQ_EVENT_BOUNCE,
1151 Chanpress = SND_SEQ_EVENT_CHANPRESS,
1152 ClientChange = SND_SEQ_EVENT_CLIENT_CHANGE,
1153 ClientExit = SND_SEQ_EVENT_CLIENT_EXIT,
1154 ClientStart = SND_SEQ_EVENT_CLIENT_START,
1155 Clock = SND_SEQ_EVENT_CLOCK,
1156 Continue = SND_SEQ_EVENT_CONTINUE,
1157 Control14 = SND_SEQ_EVENT_CONTROL14,
1158 Controller = SND_SEQ_EVENT_CONTROLLER,
1159 Echo = SND_SEQ_EVENT_ECHO,
1160 Keypress = SND_SEQ_EVENT_KEYPRESS,
1161 Keysign = SND_SEQ_EVENT_KEYSIGN,
1162 None = SND_SEQ_EVENT_NONE,
1163 Nonregparam = SND_SEQ_EVENT_NONREGPARAM,
1164 Note = SND_SEQ_EVENT_NOTE,
1165 Noteoff = SND_SEQ_EVENT_NOTEOFF,
1166 Noteon = SND_SEQ_EVENT_NOTEON,
1167 Oss = SND_SEQ_EVENT_OSS,
1168 Pgmchange = SND_SEQ_EVENT_PGMCHANGE,
1169 Pitchbend = SND_SEQ_EVENT_PITCHBEND,
1170 PortChange = SND_SEQ_EVENT_PORT_CHANGE,
1171 PortExit = SND_SEQ_EVENT_PORT_EXIT,
1172 PortStart = SND_SEQ_EVENT_PORT_START,
1173 PortSubscribed = SND_SEQ_EVENT_PORT_SUBSCRIBED,
1174 PortUnsubscribed = SND_SEQ_EVENT_PORT_UNSUBSCRIBED,
1175 Qframe = SND_SEQ_EVENT_QFRAME,
1176 QueueSkew = SND_SEQ_EVENT_QUEUE_SKEW,
1177 Regparam = SND_SEQ_EVENT_REGPARAM,
1178 Reset = SND_SEQ_EVENT_RESET,
1179 Result = SND_SEQ_EVENT_RESULT,
1180 Sensing = SND_SEQ_EVENT_SENSING,
1181 SetposTick = SND_SEQ_EVENT_SETPOS_TICK,
1182 SetposTime = SND_SEQ_EVENT_SETPOS_TIME,
1183 Songpos = SND_SEQ_EVENT_SONGPOS,
1184 Songsel = SND_SEQ_EVENT_SONGSEL,
1185 Start = SND_SEQ_EVENT_START,
1186 Stop = SND_SEQ_EVENT_STOP,
1187 SyncPos = SND_SEQ_EVENT_SYNC_POS,
1188 Sysex = SND_SEQ_EVENT_SYSEX,
1189 System = SND_SEQ_EVENT_SYSTEM,
1190 Tempo = SND_SEQ_EVENT_TEMPO,
1191 Tick = SND_SEQ_EVENT_TICK,
1192 Timesign = SND_SEQ_EVENT_TIMESIGN,
1193 TuneRequest = SND_SEQ_EVENT_TUNE_REQUEST,
1194 Usr0 = SND_SEQ_EVENT_USR0,
1195 Usr1 = SND_SEQ_EVENT_USR1,
1196 Usr2 = SND_SEQ_EVENT_USR2,
1197 Usr3 = SND_SEQ_EVENT_USR3,
1198 Usr4 = SND_SEQ_EVENT_USR4,
1199 Usr5 = SND_SEQ_EVENT_USR5,
1200 Usr6 = SND_SEQ_EVENT_USR6,
1201 Usr7 = SND_SEQ_EVENT_USR7,
1202 Usr8 = SND_SEQ_EVENT_USR8,
1203 Usr9 = SND_SEQ_EVENT_USR9,
1204 UsrVar0 = SND_SEQ_EVENT_USR_VAR0,
1205 UsrVar1 = SND_SEQ_EVENT_USR_VAR1,
1206 UsrVar2 = SND_SEQ_EVENT_USR_VAR2,
1207 UsrVar3 = SND_SEQ_EVENT_USR_VAR3,
1208 UsrVar4 = SND_SEQ_EVENT_USR_VAR4,
1209);
1210
1211/// [snd_seq_queue_tempo_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html) wrapper
1212pub struct QueueTempo(*mut alsa::snd_seq_queue_tempo_t);
1213
1214unsafe impl Send for QueueTempo {}
1215
1216impl Drop for QueueTempo {
1217 fn drop(&mut self) { unsafe { alsa::snd_seq_queue_tempo_free(self.0) } }
1218}
1219
1220impl QueueTempo {
1221 fn new() -> Result<Self> {
1222 let mut q = ptr::null_mut();
1223 acheck!(snd_seq_queue_tempo_malloc(&mut q)).map(|_| QueueTempo(q))
1224 }
1225
1226 /// Creates a new QueueTempo with all fields set to zero.
1227 pub fn empty() -> Result<Self> {
1228 let q = QueueTempo::new()?;
1229 unsafe { ptr::write_bytes(q.0 as *mut u8, 0, alsa::snd_seq_queue_tempo_sizeof()) };
1230 Ok(q)
1231 }
1232
1233 pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_queue_tempo_get_queue(self.0) as i32 } }
1234 pub fn get_tempo(&self) -> u32 { unsafe { alsa::snd_seq_queue_tempo_get_tempo(self.0) as u32 } }
1235 pub fn get_ppq(&self) -> i32 { unsafe { alsa::snd_seq_queue_tempo_get_ppq(self.0) as i32 } }
1236 pub fn get_skew(&self) -> u32 { unsafe { alsa::snd_seq_queue_tempo_get_skew(self.0) as u32 } }
1237 pub fn get_skew_base(&self) -> u32 { unsafe { alsa::snd_seq_queue_tempo_get_skew_base(self.0) as u32 } }
1238
1239// pub fn set_queue(&self, value: i32) { unsafe { alsa::snd_seq_queue_tempo_set_queue(self.0, value as c_int) } }
1240 pub fn set_tempo(&self, value: u32) { unsafe { alsa::snd_seq_queue_tempo_set_tempo(self.0, value as c_uint) } }
1241 pub fn set_ppq(&self, value: i32) { unsafe { alsa::snd_seq_queue_tempo_set_ppq(self.0, value as c_int) } }
1242 pub fn set_skew(&self, value: u32) { unsafe { alsa::snd_seq_queue_tempo_set_skew(self.0, value as c_uint) } }
1243 pub fn set_skew_base(&self, value: u32) { unsafe { alsa::snd_seq_queue_tempo_set_skew_base(self.0, value as c_uint) } }
1244}
1245
1246/// [snd_seq_queue_status_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html) wrapper
1247pub struct QueueStatus(*mut alsa::snd_seq_queue_status_t);
1248
1249unsafe impl Send for QueueStatus {}
1250
1251impl Drop for QueueStatus {
1252 fn drop(&mut self) { unsafe { alsa::snd_seq_queue_status_free(self.0) } }
1253}
1254
1255impl QueueStatus {
1256 fn new() -> Result<Self> {
1257 let mut q: *mut _snd_seq_queue_status = ptr::null_mut();
1258 acheck!(snd_seq_queue_status_malloc(&mut q)).map(|_| QueueStatus(q))
1259 }
1260
1261 /// Creates a new QueueStatus with all fields set to zero.
1262 pub fn empty() -> Result<Self> {
1263 let q: QueueStatus = QueueStatus::new()?;
1264 unsafe { ptr::write_bytes(dst:q.0 as *mut u8, val:0, count:alsa::snd_seq_queue_status_sizeof()) };
1265 Ok(q)
1266 }
1267
1268 pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_queue_status_get_queue(self.0) as i32 } }
1269 pub fn get_events(&self) -> i32 { unsafe { alsa::snd_seq_queue_status_get_events(self.0) as i32 } }
1270 pub fn get_tick_time(&self) -> u32 { unsafe {alsa::snd_seq_queue_status_get_tick_time(self.0) as u32 } }
1271 pub fn get_real_time(&self) -> time::Duration { unsafe {
1272 let t: &snd_seq_real_time = &(*alsa::snd_seq_queue_status_get_real_time(self.0));
1273 time::Duration::new(secs:t.tv_sec as u64, nanos:t.tv_nsec as u32)
1274 } }
1275 pub fn get_status(&self) -> u32 { unsafe { alsa::snd_seq_queue_status_get_status(self.0) as u32 } }
1276}
1277
1278/// [snd_seq_remove_events_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_event.html) wrapper
1279pub struct RemoveEvents(*mut alsa::snd_seq_remove_events_t);
1280
1281unsafe impl Send for RemoveEvents {}
1282
1283impl Drop for RemoveEvents {
1284 fn drop(&mut self) { unsafe { alsa::snd_seq_remove_events_free(self.0) } }
1285}
1286
1287impl RemoveEvents {
1288 pub fn new() -> Result<Self> {
1289 let mut q = ptr::null_mut();
1290 acheck!(snd_seq_remove_events_malloc(&mut q)).map(|_| RemoveEvents(q))
1291 }
1292
1293 pub fn get_condition(&self) -> Remove { unsafe {
1294 Remove::from_bits_truncate(alsa::snd_seq_remove_events_get_condition(self.0) as u32)
1295 } }
1296 pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_remove_events_get_queue(self.0) as i32 } }
1297 pub fn get_time(&self) -> time::Duration { unsafe {
1298 let d = ptr::read(alsa::snd_seq_remove_events_get_time(self.0));
1299 let t = &d.time;
1300
1301 time::Duration::new(t.tv_sec as u64, t.tv_nsec as u32)
1302 } }
1303 pub fn get_dest(&self) -> Addr { unsafe {
1304 let a = &(*alsa::snd_seq_remove_events_get_dest(self.0));
1305
1306 Addr { client: a.client as i32, port: a.port as i32 }
1307 } }
1308 pub fn get_channel(&self) -> i32 { unsafe { alsa::snd_seq_remove_events_get_channel(self.0) as i32 } }
1309 pub fn get_event_type(&self) -> Result<EventType> { unsafe {
1310 EventType::from_c_int(alsa::snd_seq_remove_events_get_event_type(self.0), "snd_seq_remove_events_get_event_type")
1311 } }
1312 pub fn get_tag(&self) -> u8 { unsafe { alsa::snd_seq_remove_events_get_tag(self.0) as u8 } }
1313
1314
1315 pub fn set_condition(&self, value: Remove) { unsafe {
1316 alsa::snd_seq_remove_events_set_condition(self.0, value.bits() as c_uint);
1317 } }
1318 pub fn set_queue(&self, value: i32) { unsafe { alsa::snd_seq_remove_events_set_queue(self.0, value as c_int) } }
1319 pub fn set_time(&self, value: time::Duration) { unsafe {
1320 let mut d: alsa::snd_seq_timestamp_t = mem::zeroed();
1321 let t = &mut d.time;
1322
1323 t.tv_sec = value.as_secs() as c_uint;
1324 t.tv_nsec = value.subsec_nanos() as c_uint;
1325
1326 alsa::snd_seq_remove_events_set_time(self.0, &d);
1327 } }
1328 pub fn set_dest(&self, value: Addr) { unsafe {
1329 let a = alsa::snd_seq_addr_t { client: value.client as c_uchar, port: value.port as c_uchar};
1330
1331 alsa::snd_seq_remove_events_set_dest(self.0, &a);
1332 } }
1333 pub fn set_channel(&self, value: i32) { unsafe { alsa::snd_seq_remove_events_set_channel(self.0, value as c_int) } }
1334 pub fn set_event_type(&self, value: EventType) { unsafe { alsa::snd_seq_remove_events_set_event_type(self.0, value as i32); } }
1335 pub fn set_tag(&self, value: u8) { unsafe { alsa::snd_seq_remove_events_set_tag(self.0, value as c_int) } }
1336}
1337
1338/// [snd_midi_event_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___m_i_d_i___event.html) Wrapper
1339///
1340/// Sequencer event <-> MIDI byte stream coder
1341pub struct MidiEvent(*mut alsa::snd_midi_event_t);
1342
1343impl Drop for MidiEvent {
1344 fn drop(&mut self) { unsafe { alsa::snd_midi_event_free(self.0) } }
1345}
1346
1347impl MidiEvent {
1348 pub fn new(bufsize: u32) -> Result<MidiEvent> {
1349 let mut q = ptr::null_mut();
1350 acheck!(snd_midi_event_new(bufsize as size_t, &mut q)).map(|_| MidiEvent(q))
1351 }
1352
1353 pub fn resize_buffer(&self, bufsize: u32) -> Result<()> { acheck!(snd_midi_event_resize_buffer(self.0, bufsize as size_t)).map(|_| ()) }
1354
1355 /// Note: this corresponds to snd_midi_event_no_status, but on and off are switched.
1356 ///
1357 /// Alsa-lib is a bit confusing here. Anyhow, set "enable" to true to enable running status.
1358 pub fn enable_running_status(&self, enable: bool) { unsafe { alsa::snd_midi_event_no_status(self.0, if enable {0} else {1}) } }
1359
1360 /// Resets both encoder and decoder
1361 pub fn init(&self) { unsafe { alsa::snd_midi_event_init(self.0) } }
1362
1363 pub fn reset_encode(&self) { unsafe { alsa::snd_midi_event_reset_encode(self.0) } }
1364
1365 pub fn reset_decode(&self) { unsafe { alsa::snd_midi_event_reset_decode(self.0) } }
1366
1367 pub fn decode(&self, buf: &mut [u8], ev: &mut Event) -> Result<usize> {
1368 ev.ensure_buf();
1369 acheck!(snd_midi_event_decode(self.0, buf.as_mut_ptr() as *mut c_uchar, buf.len() as c_long, &ev.0)).map(|r| r as usize)
1370 }
1371
1372 /// In case of success, returns a tuple of (bytes consumed from buf, found Event).
1373 pub fn encode<'a>(&'a mut self, buf: &[u8]) -> Result<(usize, Option<Event<'a>>)> {
1374 // The ALSA documentation clearly states that the event will be valid as long as the Encoder
1375 // is not messed with (because the data pointer for sysex events may point into the Encoder's
1376 // buffer). We make this safe by taking self by unique reference and coupling it to
1377 // the event's lifetime.
1378 let mut ev = unsafe { mem::zeroed() };
1379 let r = acheck!(snd_midi_event_encode(self.0, buf.as_ptr() as *const c_uchar, buf.len() as c_long, &mut ev))?;
1380 let e = if ev.type_ == alsa::SND_SEQ_EVENT_NONE as u8 {
1381 None
1382 } else {
1383 Some(unsafe { Event::extract(&mut ev, "snd_midi_event_encode") }?)
1384 };
1385 Ok((r as usize, e))
1386 }
1387}
1388
1389#[test]
1390fn print_seqs() {
1391 use std::ffi::CString;
1392 let s: Seq = super::Seq::open(name:None, dir:None, nonblock:false).unwrap();
1393 s.set_client_name(&CString::new("rust_test_print_seqs").unwrap()).unwrap();
1394 let clients: Vec<_> = ClientIter::new(&s).collect();
1395 for a: &ClientInfo in &clients {
1396 let ports: Vec<_> = PortIter::new(&s, a.get_client()).collect();
1397 println!("{:?}: {:?}", a, ports);
1398 }
1399}
1400
1401#[test]
1402fn seq_subscribe() {
1403 use std::ffi::CString;
1404 let s: Seq = super::Seq::open(name:None, dir:None, nonblock:false).unwrap();
1405 s.set_client_name(&CString::new("rust_test_seq_subscribe").unwrap()).unwrap();
1406 let timer_info: PortInfo = s.get_any_port_info(Addr { client: 0, port: 0 }).unwrap();
1407 assert_eq!(timer_info.get_name().unwrap(), "Timer");
1408 let info: PortInfo = PortInfo::empty().unwrap();
1409 let _port: Result<(), Error> = s.create_port(&info);
1410 let subs: PortSubscribe = PortSubscribe::empty().unwrap();
1411 subs.set_sender(Addr { client: 0, port: 0 });
1412 subs.set_dest(Addr { client: s.client_id().unwrap(), port: info.get_port() });
1413 s.subscribe_port(&subs).unwrap();
1414}
1415
1416#[test]
1417fn seq_loopback() {
1418 use std::ffi::CString;
1419 let s = super::Seq::open(Some(&CString::new("default").unwrap()), None, false).unwrap();
1420 s.set_client_name(&CString::new("rust_test_seq_loopback").unwrap()).unwrap();
1421
1422 // Create ports
1423 let sinfo = PortInfo::empty().unwrap();
1424 sinfo.set_capability(PortCap::READ | PortCap::SUBS_READ);
1425 sinfo.set_type(PortType::MIDI_GENERIC | PortType::APPLICATION);
1426 s.create_port(&sinfo).unwrap();
1427 let sport = sinfo.get_port();
1428 let dinfo = PortInfo::empty().unwrap();
1429 dinfo.set_capability(PortCap::WRITE | PortCap::SUBS_WRITE);
1430 dinfo.set_type(PortType::MIDI_GENERIC | PortType::APPLICATION);
1431 s.create_port(&dinfo).unwrap();
1432 let dport = dinfo.get_port();
1433
1434 // Connect them
1435 let subs = PortSubscribe::empty().unwrap();
1436 subs.set_sender(Addr { client: s.client_id().unwrap(), port: sport });
1437 subs.set_dest(Addr { client: s.client_id().unwrap(), port: dport });
1438 s.subscribe_port(&subs).unwrap();
1439 println!("Connected {:?} to {:?}", subs.get_sender(), subs.get_dest());
1440
1441 // Send a note!
1442 let note = EvNote { channel: 0, note: 64, duration: 100, velocity: 100, off_velocity: 64 };
1443 let mut e = Event::new(EventType::Noteon, &note);
1444 e.set_subs();
1445 e.set_direct();
1446 e.set_source(sport);
1447 println!("Sending {:?}", e);
1448 s.event_output(&mut e).unwrap();
1449 s.drain_output().unwrap();
1450
1451 // Receive the note!
1452 let mut input = s.input();
1453 let e2 = input.event_input().unwrap();
1454 println!("Receiving {:?}", e2);
1455 assert_eq!(e2.get_type(), EventType::Noteon);
1456 assert_eq!(e2.get_data(), Some(note));
1457}
1458
1459#[test]
1460fn seq_encode_sysex() {
1461 let mut me: MidiEvent = MidiEvent::new(bufsize:16).unwrap();
1462 let sysex: &[u8; 9] = &[0xf0, 1, 2, 3, 4, 5, 6, 7, 0xf7];
1463 let (s: usize, ev: Option>) = me.encode(buf:sysex).unwrap();
1464 assert_eq!(s, 9);
1465 let ev: Event<'_> = ev.unwrap();
1466 let v: &[u8] = ev.get_ext().unwrap();
1467 assert_eq!(&*v, sysex);
1468}
1469
1470#[test]
1471fn seq_decode_sysex() {
1472 let sysex: [u8; 9] = [0xf0, 1, 2, 3, 4, 5, 6, 7, 0xf7];
1473 let mut ev: Event<'_> = Event::new_ext(t:EventType::Sysex, &sysex[..]);
1474 let me: MidiEvent = MidiEvent::new(bufsize:0).unwrap();
1475 let mut buffer: Vec = vec![0; sysex.len()];
1476 assert_eq!(me.decode(&mut buffer[..], &mut ev).unwrap(), sysex.len());
1477 assert_eq!(buffer, sysex);
1478}
1479
1480#[test]
1481#[should_panic]
1482fn seq_get_input_twice() {
1483 use std::ffi::CString;
1484 let s: Seq = super::Seq::open(name:None, dir:None, nonblock:false).unwrap();
1485 s.set_client_name(&CString::new("rust_test_seq_get_input_twice").unwrap()).unwrap();
1486 let input1: Input<'_> = s.input();
1487 let input2: Input<'_> = s.input(); // this should panic
1488 let _ = (input1, input2);
1489}
1490
1491#[test]
1492fn seq_has_data() {
1493 for v: &EventType in EventType::all() {
1494 let v: EventType = *v;
1495 let mut i: i32 = 0;
1496 if <() as EventData>::has_data(v) { i += 1; }
1497 if <[u8; 12] as EventData>::has_data(v) { i += 1; }
1498 if Event::has_ext_data(v) { i += 1; }
1499 if EvNote::has_data(v) { i += 1; }
1500 if EvCtrl::has_data(v) { i += 1; }
1501 if Addr::has_data(v) { i += 1; }
1502 if Connect::has_data(v) { i += 1; }
1503 if EvResult::has_data(v) { i += 1; }
1504 if EvQueueControl::<()>::has_data(v) { i += 1; }
1505 if EvQueueControl::<u32>::has_data(v) { i += 1; }
1506 if EvQueueControl::<i32>::has_data(v) { i += 1; }
1507 if EvQueueControl::<time::Duration>::has_data(v) { i += 1; }
1508 if i != 1 { panic!("{:?}: {} has_data", v, i) }
1509 }
1510}
1511
1512#[test]
1513fn seq_remove_events() -> std::result::Result<(), Box<dyn std::error::Error>> {
1514 let info: RemoveEvents = RemoveEvents::new()?;
1515
1516
1517 info.set_condition(Remove::INPUT | Remove::DEST | Remove::TIME_BEFORE | Remove::TAG_MATCH);
1518 info.set_queue(123);
1519 info.set_time(time::Duration::new(secs:456, nanos:789));
1520 info.set_dest(Addr { client: 212, port: 121 });
1521 info.set_channel(15);
1522 info.set_event_type(EventType::Noteon);
1523 info.set_tag(213);
1524
1525 assert_eq!(info.get_condition(), Remove::INPUT | Remove::DEST | Remove::TIME_BEFORE | Remove::TAG_MATCH);
1526 assert_eq!(info.get_queue(), 123);
1527 assert_eq!(info.get_time(), time::Duration::new(456, 789));
1528 assert_eq!(info.get_dest(), Addr { client: 212, port: 121 });
1529 assert_eq!(info.get_channel(), 15);
1530 assert_eq!(info.get_event_type()?, EventType::Noteon);
1531 assert_eq!(info.get_tag(), 213);
1532
1533 Ok(())
1534}
1535
1536#[test]
1537fn seq_portsubscribeiter() {
1538 let s = super::Seq::open(None, None, false).unwrap();
1539
1540 // Create ports
1541 let sinfo = PortInfo::empty().unwrap();
1542 sinfo.set_capability(PortCap::READ | PortCap::SUBS_READ);
1543 sinfo.set_type(PortType::MIDI_GENERIC | PortType::APPLICATION);
1544 s.create_port(&sinfo).unwrap();
1545 let sport = sinfo.get_port();
1546 let dinfo = PortInfo::empty().unwrap();
1547 dinfo.set_capability(PortCap::WRITE | PortCap::SUBS_WRITE);
1548 dinfo.set_type(PortType::MIDI_GENERIC | PortType::APPLICATION);
1549 s.create_port(&dinfo).unwrap();
1550 let dport = dinfo.get_port();
1551
1552 // Connect them
1553 let subs = PortSubscribe::empty().unwrap();
1554 subs.set_sender(Addr { client: s.client_id().unwrap(), port: sport });
1555 subs.set_dest(Addr { client: s.client_id().unwrap(), port: dport });
1556 s.subscribe_port(&subs).unwrap();
1557
1558 // Query READ subs from sport's point of view
1559 let read_subs: Vec<PortSubscribe> = PortSubscribeIter::new(&s,
1560 Addr {client: s.client_id().unwrap(), port: sport },
1561 QuerySubsType::READ).collect();
1562 assert_eq!(read_subs.len(), 1);
1563 assert_eq!(read_subs[0].get_sender(), subs.get_sender());
1564 assert_eq!(read_subs[0].get_dest(), subs.get_dest());
1565
1566 let write_subs: Vec<PortSubscribe> = PortSubscribeIter::new(&s,
1567 Addr {client: s.client_id().unwrap(), port: sport },
1568 QuerySubsType::WRITE).collect();
1569 assert_eq!(write_subs.len(), 0);
1570
1571 // Now query WRITE subs from dport's point of view
1572 let write_subs: Vec<PortSubscribe> = PortSubscribeIter::new(&s,
1573 Addr {client: s.client_id().unwrap(), port: dport },
1574 QuerySubsType::WRITE).collect();
1575 assert_eq!(write_subs.len(), 1);
1576 assert_eq!(write_subs[0].get_sender(), subs.get_sender());
1577 assert_eq!(write_subs[0].get_dest(), subs.get_dest());
1578}
1579