/// Check if the packet list is empty. /// pubfn is_empty(&self) -> bool { self.len() == 0
}
/// Get the number of packets in the list. /// pubfn len(&self) -> usize { self.0.numPackets as usize
}
/// Get an iterator for the packets in the list. /// pubfn iter(&self) -> EventListIter {
EventListIter {
count: self.len(),
packet_ptr: std::ptr::addr_of!(self.0.packet) as *const MIDIEventPacket,
_phantom: PhantomData,
}
}
/// For internal usage only. /// Requires this instance to actually point to a valid MIDIEventList pub(crate) unsafefn as_ptr(&self) -> *const MIDIEventList { selfas *const EventList as *const MIDIEventList
}
}
/// Get the packet data. This method just gives raw MIDI words. You would need another /// library to decode them and work with higher level events. /// pubfn data(&self) -> &[u32] { let data_ptr = self.0.words.as_ptr(); let data_len = self.0.wordCount as usize; unsafe { slice::from_raw_parts(data_ptr, data_len) }
}
}
impl std::fmt::Debug for EventPacket { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, " {:024}:", self.timestamp())?; for word inself.data().iter() {
write!(f, " {:08x}", word)?;
}
Ok(())
}
}
/// Create an empty `EventBuffer` for a given [Protocol] without allocating. /// pubfn new(protocol: Protocol) -> Self { Self::with_capacity(Storage::INLINE_SIZE, protocol)
}
/// Create an empty `EventBuffer` of a given capacity for a given [Protocol]. /// pubfn with_capacity(capacity: usize, protocol: Protocol) -> Self { letmut storage = Storage::with_capacity(capacity); let event_list_ptr = unsafe { storage.as_mut_ptr::<MIDIEventList>() }; let current_packet_ptr = unsafe { MIDIEventListInit(event_list_ptr, protocol.into()) }; let current_packet_offset = unsafe {
(current_packet_ptr as *const u8).offset_from(event_list_ptr as *const u8) as usize
}; Self {
storage,
current_packet_offset,
}
}
/// Get underlying buffer capacity in bytes /// pubfn capacity(&self) -> usize { self.storage.capacity()
}
/// Add a new packet containing the provided timestamp and data. /// It consumes the instance and returns it modified with the new packet. /// /// See [EventBuffer::push] for further details. /// /// Example: /// /// ``` /// use coremidi::{Protocol, Timestamp, EventBuffer}; /// /// let buffer = EventBuffer::new(Protocol::Midi20) /// .with_packet(0, &[0x40903c00, 0xffff0000]); // Note On for Middle C /// /// assert_eq!(buffer.len(), 1); /// assert_eq!( /// buffer.iter() /// .map(|packet| (packet.timestamp(), packet.data().to_vec())) /// .collect::<Vec<(Timestamp, Vec<u32>)>>(), /// vec![(0, vec![0x40903c00, 0xffff0000])], /// ) /// ``` pubfn with_packet(mutself, timestamp: Timestamp, data: &[u32]) -> Self { self.push(timestamp, data); self
}
/// Add a new event containing the provided timestamp and data. /// /// According to the official documentation for CoreMIDI, the timestamp represents /// the time at which the events are to be played, where zero means "now". /// The timestamp applies to the first MIDI word in the packet. /// /// An event must not have a timestamp that is smaller than that of a previous event /// in the same `EventBuffer` /// /// Example: /// /// ``` /// use coremidi::{EventBuffer, Protocol, Timestamp}; /// /// let mut buffer = EventBuffer::new(Protocol::Midi20); /// buffer.push(0, &[0x40903c00, 0xffff0000]); // Note On for Middle C /// /// assert_eq!(buffer.len(), 1); /// assert_eq!( /// buffer.iter() /// .map(|packet| (packet.timestamp(), packet.data().to_vec())) /// .collect::<Vec<(Timestamp, Vec<u32>)>>(), /// vec![(0, vec![0x40903c00, 0xffff0000])], /// ) /// ``` pubfn push(&mutself, timestamp: Timestamp, data: &[u32]) -> &le='color:red'>mutSelf { self.ensure_capacity(data.len());
let packet_list_ptr = unsafe { self.storage.as_mut_ptr::<MIDIEventList>() }; let current_packet_ptr = unsafe { self.storage.as_ptr::<u8>().add(self.current_packet_offset) as *mut MIDIEventPacket
}; let current_packet_ptr = unsafe {
MIDIEventListAdd(
packet_list_ptr, self.storage.capacity() as u64,
current_packet_ptr,
timestamp,
data.len() as u64,
data.as_ptr(),
)
};
self.current_packet_offset = unsafe {
(current_packet_ptr as *const u8).offset_from(packet_list_ptr as *const u8) as usize
};
self
}
/// Clears the buffer, removing all packets. /// Note that this method has no effect on the allocated capacity of the buffer. pubfn clear(&mutself) { let event_list_ptr = unsafe { self.storage.as_mut_ptr::<MIDIEventList>() }; let protocol = unsafe { (*event_list_ptr).protocol }; let current_packet_ptr = unsafe { MIDIEventListInit(event_list_ptr, protocol) }; self.current_packet_offset = unsafe {
(current_packet_ptr as *const u8).offset_from(event_list_ptr as *const u8) as usize
};
}
#[derive(Clone)] pub(crate) enum Storage { /// Inline stores the data directly on the stack, if it is small enough. /// NOTE: using u32 ensures correct alignment (required on ARM)
Inline([u32; Storage::INLINE_SIZE / 4]), /// External is used whenever the size of the data exceeds INLINE_PACKET_BUFFER_SIZE. /// This means that the size of the contained vector is always greater than INLINE_PACKET_BUFFER_SIZE.
External(Vec<u32>),
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.