1 | //! MIDI sequencer I/O and enumeration |
2 | |
3 | use libc::{c_uint, c_int, c_short, c_uchar, c_void, c_long, size_t, pollfd}; |
4 | use super::error::*; |
5 | use crate::alsa; |
6 | use super::{Direction, poll}; |
7 | use std::{ptr, fmt, mem, slice, time, cell}; |
8 | use std::str::{FromStr, Split}; |
9 | use std::ffi::CStr; |
10 | use std::borrow::Cow; |
11 | |
12 | // Workaround for improper alignment of snd_seq_ev_ext_t in alsa-sys |
13 | #[repr (packed)] |
14 | struct 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`. |
24 | pub struct Seq(*mut alsa::snd_seq_t, cell::Cell<bool>); |
25 | |
26 | unsafe impl Send for Seq {} |
27 | |
28 | impl Drop for Seq { |
29 | fn drop(&mut self) { unsafe { alsa::snd_seq_close(self.0) }; } |
30 | } |
31 | |
32 | impl 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. |
185 | pub struct Input<'a>(&'a Seq); |
186 | |
187 | impl<'a> Drop for Input<'a> { |
188 | fn drop(&mut self) { (self.0).1.set(val:false) } |
189 | } |
190 | |
191 | impl<'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 | |
221 | fn 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 | |
229 | impl<'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 |
248 | pub struct ClientInfo(*mut alsa::snd_seq_client_info_t); |
249 | |
250 | unsafe impl Send for ClientInfo {} |
251 | |
252 | impl Drop for ClientInfo { |
253 | fn drop(&mut self) { |
254 | unsafe { alsa::snd_seq_client_info_free(self.0) }; |
255 | } |
256 | } |
257 | |
258 | impl 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 | |
279 | impl 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). |
287 | pub struct ClientIter<'a>(&'a Seq, i32); |
288 | |
289 | impl<'a> ClientIter<'a> { |
290 | pub fn new(seq: &'a Seq) -> Self { ClientIter(seq, -1) } |
291 | } |
292 | |
293 | impl<'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 |
306 | pub struct PortInfo(*mut alsa::snd_seq_port_info_t); |
307 | |
308 | unsafe impl Send for PortInfo {} |
309 | |
310 | impl Drop for PortInfo { |
311 | fn drop(&mut self) { |
312 | unsafe { alsa::snd_seq_port_info_free(self.0) }; |
313 | } |
314 | } |
315 | |
316 | impl 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 | |
400 | impl 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). |
408 | pub struct PortIter<'a>(&'a Seq, i32, i32); |
409 | |
410 | impl<'a> PortIter<'a> { |
411 | pub fn new(seq: &'a Seq, client: i32) -> Self { PortIter(seq, client, -1) } |
412 | } |
413 | |
414 | impl<'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 | |
427 | bitflags! { |
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 | |
443 | bitflags! { |
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 | |
466 | bitflags! { |
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)] |
487 | pub struct Addr { |
488 | pub client: i32, |
489 | pub port: i32, |
490 | } |
491 | |
492 | impl 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 | |
514 | impl 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 |
521 | pub struct PortSubscribe(*mut alsa::snd_seq_port_subscribe_t); |
522 | |
523 | unsafe impl Send for PortSubscribe {} |
524 | |
525 | impl Drop for PortSubscribe { |
526 | fn drop(&mut self) { unsafe { alsa::snd_seq_port_subscribe_free(self.0) }; } |
527 | } |
528 | |
529 | impl 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)] |
576 | pub 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) |
583 | struct QuerySubscribe(*mut alsa::snd_seq_query_subscribe_t); |
584 | |
585 | unsafe impl Send for QuerySubscribe {} |
586 | |
587 | impl Drop for QuerySubscribe { |
588 | fn drop(&mut self) { unsafe { alsa::snd_seq_query_subscribe_free(self.0) } } |
589 | } |
590 | |
591 | impl 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. |
619 | pub struct PortSubscribeIter<'a> { |
620 | seq: &'a Seq, |
621 | addr: Addr, |
622 | query_subs_type: QuerySubsType, |
623 | index: i32 |
624 | } |
625 | |
626 | impl<'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 | |
632 | impl<'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). |
676 | pub struct Event<'a>(alsa::snd_seq_event_t, EventType, Option<Cow<'a, [u8]>>); |
677 | |
678 | unsafe impl<'a> Send for Event<'a> {} |
679 | |
680 | impl<'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 | |
837 | impl<'a> Clone for Event<'a> { |
838 | fn clone(&self) -> Self { Event(unsafe { ptr::read(&self.0) }, self.1, self.2.clone()) } |
839 | } |
840 | |
841 | impl<'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`. |
863 | pub 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 | |
872 | impl 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 | |
884 | impl 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)] |
913 | pub 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 | |
921 | impl 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)] |
944 | pub struct EvCtrl { |
945 | pub channel: u8, |
946 | pub param: u32, |
947 | pub value: i32, |
948 | } |
949 | |
950 | impl 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 | |
978 | impl 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 |
1001 | pub struct Connect { |
1002 | pub sender: Addr, |
1003 | pub dest: Addr, |
1004 | } |
1005 | |
1006 | impl 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. |
1035 | pub struct EvQueueControl<T> { |
1036 | pub queue: i32, |
1037 | pub value: T, |
1038 | } |
1039 | |
1040 | impl 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 | |
1060 | impl 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 | |
1077 | impl 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 | |
1096 | impl 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. |
1120 | pub struct EvResult { |
1121 | pub event: i32, |
1122 | pub result: i32, |
1123 | } |
1124 | |
1125 | impl 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 | |
1145 | alsa_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 |
1212 | pub struct QueueTempo(*mut alsa::snd_seq_queue_tempo_t); |
1213 | |
1214 | unsafe impl Send for QueueTempo {} |
1215 | |
1216 | impl Drop for QueueTempo { |
1217 | fn drop(&mut self) { unsafe { alsa::snd_seq_queue_tempo_free(self.0) } } |
1218 | } |
1219 | |
1220 | impl 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 |
1247 | pub struct QueueStatus(*mut alsa::snd_seq_queue_status_t); |
1248 | |
1249 | unsafe impl Send for QueueStatus {} |
1250 | |
1251 | impl Drop for QueueStatus { |
1252 | fn drop(&mut self) { unsafe { alsa::snd_seq_queue_status_free(self.0) } } |
1253 | } |
1254 | |
1255 | impl 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 |
1279 | pub struct RemoveEvents(*mut alsa::snd_seq_remove_events_t); |
1280 | |
1281 | unsafe impl Send for RemoveEvents {} |
1282 | |
1283 | impl Drop for RemoveEvents { |
1284 | fn drop(&mut self) { unsafe { alsa::snd_seq_remove_events_free(self.0) } } |
1285 | } |
1286 | |
1287 | impl 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 |
1341 | pub struct MidiEvent(*mut alsa::snd_midi_event_t); |
1342 | |
1343 | impl Drop for MidiEvent { |
1344 | fn drop(&mut self) { unsafe { alsa::snd_midi_event_free(self.0) } } |
1345 | } |
1346 | |
1347 | impl 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 ] |
1390 | fn 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 ] |
1402 | fn 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 ] |
1417 | fn 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, ¬e); |
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 ] |
1460 | fn 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 ] |
1471 | fn 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 ] |
1482 | fn 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 ] |
1492 | fn 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 ] |
1513 | fn 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 ] |
1537 | fn 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 | |