1 use coremidi_sys::{ 2 ItemCount, MIDIEndpointDispose, MIDIGetDestination, MIDIGetNumberOfDestinations, 3 }; 4 5 use std::ops::Deref; 6 7 use crate::{callback::BoxedCallback, object::Object, packets::PacketList}; 8 9 use super::Endpoint; 10 11 /// A [MIDI source](https://developer.apple.com/reference/coremidi/midiendpointref) owned by an entity. 12 /// 13 /// A source can be created from an index like this: 14 /// 15 /// ```rust,no_run 16 /// let source = coremidi::Destination::from_index(0).unwrap(); 17 /// println!("The source at index 0 has display name '{}'", source.display_name().unwrap()); 18 /// ``` 19 /// 20 #[derive(Debug)] 21 pub struct Destination { 22 pub(crate) endpoint: Endpoint, 23 } 24 25 impl Destination { 26 /// Create a destination endpoint from its index. 27 /// See [MIDIGetDestination](https://developer.apple.com/reference/coremidi/1495108-midigetdestination) 28 /// from_index(index: usize) -> Option<Destination>29 pub fn from_index(index: usize) -> Option<Destination> { 30 let endpoint_ref = unsafe { MIDIGetDestination(index as ItemCount) }; 31 match endpoint_ref { 32 0 => None, 33 _ => Some(Destination { 34 endpoint: Endpoint { 35 object: Object(endpoint_ref), 36 }, 37 }), 38 } 39 } 40 } 41 42 impl Deref for Destination { 43 type Target = Endpoint; 44 deref(&self) -> &Endpoint45 fn deref(&self) -> &Endpoint { 46 &self.endpoint 47 } 48 } 49 50 /// Destination endpoints available in the system. 51 /// 52 /// The number of destinations available in the system can be retrieved with: 53 /// 54 /// ``` 55 /// let number_of_destinations = coremidi::Destinations::count(); 56 /// ``` 57 /// 58 /// The destinations in the system can be iterated as: 59 /// 60 /// ```rust,no_run 61 /// for destination in coremidi::Destinations { 62 /// println!("{}", destination.display_name().unwrap()); 63 /// } 64 /// ``` 65 /// 66 pub struct Destinations; 67 68 impl Destinations { 69 /// Get the number of destinations available in the system for sending MIDI messages. 70 /// See [MIDIGetNumberOfDestinations](https://developer.apple.com/reference/coremidi/1495309-midigetnumberofdestinations). 71 /// count() -> usize72 pub fn count() -> usize { 73 unsafe { MIDIGetNumberOfDestinations() as usize } 74 } 75 } 76 77 impl IntoIterator for Destinations { 78 type Item = Destination; 79 type IntoIter = DestinationsIterator; 80 into_iter(self) -> Self::IntoIter81 fn into_iter(self) -> Self::IntoIter { 82 DestinationsIterator { 83 index: 0, 84 count: Self::count(), 85 } 86 } 87 } 88 89 pub struct DestinationsIterator { 90 index: usize, 91 count: usize, 92 } 93 94 impl Iterator for DestinationsIterator { 95 type Item = Destination; 96 next(&mut self) -> Option<Destination>97 fn next(&mut self) -> Option<Destination> { 98 if self.index < self.count { 99 let destination = Destination::from_index(self.index); 100 self.index += 1; 101 destination 102 } else { 103 None 104 } 105 } 106 } 107 108 /// A [MIDI virtual destination](https://developer.apple.com/reference/coremidi/1495347-mididestinationcreate) owned by a client. 109 /// 110 /// A virtual destination can be created like: 111 /// 112 /// ```rust,no_run 113 /// let client = coremidi::Client::new("example-client").unwrap(); 114 /// client.virtual_destination("example-destination", |packet_list| println!("{}", packet_list)).unwrap(); 115 /// ``` 116 /// 117 #[derive(Debug)] 118 pub struct VirtualDestination { 119 // Note: the order is important here, endpoint needs to be dropped first 120 pub(crate) endpoint: Endpoint, 121 pub(crate) callback: BoxedCallback<PacketList>, 122 } 123 124 impl VirtualDestination {} 125 126 impl Deref for VirtualDestination { 127 type Target = Endpoint; 128 deref(&self) -> &Endpoint129 fn deref(&self) -> &Endpoint { 130 &self.endpoint 131 } 132 } 133 134 impl Drop for VirtualDestination { drop(&mut self)135 fn drop(&mut self) { 136 unsafe { MIDIEndpointDispose(self.endpoint.object.0) }; 137 } 138 } 139