From 14eff2e4f1b4868824ada3acc6156139f09d8b22 Mon Sep 17 00:00:00 2001 From: Jason Grlicky Date: Tue, 2 Jun 2020 11:19:13 -0700 Subject: [PATCH] Documented How to Receive Client Notifications (#28) --- README.md | 2 ++ examples/notifications.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/client.rs | 6 ++++++ src/lib.rs | 4 ++-- 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 examples/notifications.rs diff --git a/README.md b/README.md index f39f0ea8a..e05283b5f 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,8 @@ These are the provided examples: - [receive](examples/receive.rs): how to create an input port and receive MIDI messages. - [virtual-source](examples/virtual-source.rs): how to create a virtual source and generate MIDI messages. - [virtual-destination](examples/virtual-destination.rs): how to create a virtual destination and receive MIDI messages. +- [properties](examples/properties.rs): how to set and get properties on MIDI objects. +- [notifications](examples/notifications.rs): how to receive MIDI client notifications. # Roadmap diff --git a/examples/notifications.rs b/examples/notifications.rs new file mode 100644 index 000000000..866e89364 --- /dev/null +++ b/examples/notifications.rs @@ -0,0 +1,39 @@ +extern crate coremidi; +extern crate core_foundation; + +use coremidi::{ + Client, + Notification, +}; + +use core_foundation::runloop::{ + CFRunLoopRunInMode, + kCFRunLoopDefaultMode, +}; + +fn main() { + println!("Logging MIDI Client Notifications"); + println!("Will Quit Automatically After 10 Seconds"); + println!(""); + + let _client = Client::new_with_notifications("example-client", print_notification).unwrap(); + + // As the MIDIClientCreate docs say (https://developer.apple.com/documentation/coremidi/1495360-midiclientcreate), + // notifications will be delivered on the run loop that was current when + // Client was created. + // + // In order to actually receive the notifications, a run loop must be + // running. Since this sample app does not use an app framework like + // UIApplication or NSApplication, it does not have a run loop running yet. + // So we start one that lasts for 10 seconds with the following line. + // + // You may not have to do this in your app - see https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW24 + // for information about when run loops are running automatically. + unsafe { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10.0, 0) + }; +} + +fn print_notification(notification: &Notification) { + println!("Received Notification: {:?} \r", notification); +} \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index 934555791..a69110b46 100644 --- a/src/client.rs +++ b/src/client.rs @@ -44,6 +44,12 @@ impl Client { /// Creates a new CoreMIDI client with support for notifications. /// See [MIDIClientCreate](https://developer.apple.com/reference/coremidi/1495360-midiclientcreate). /// + /// The notification callback will be called on the [run loop](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html) + /// that was current when this associated function is called. + /// + /// It follows that this particular run loop needs to be running in order to + /// actually receive notifications. The run loop can be started after the + /// client has been created if need be. pub fn new_with_notifications(name: &str, callback: F) -> Result where F: FnMut(&Notification) + Send + 'static { diff --git a/src/lib.rs b/src/lib.rs index e692b2433..5a711092c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,8 +97,8 @@ unsafe impl Send for BoxedCallback {} impl Drop for BoxedCallback { fn drop(&mut self) { - unsafe { - if !self.0.is_null() { + if !self.0.is_null() { + unsafe { let _ = Box::from_raw(self.0); } }