Skip to content

Commit

Permalink
Documented How to Receive Client Notifications (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasongrlicky authored Jun 2, 2020
1 parent c1bee2f commit 14eff2e
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
39 changes: 39 additions & 0 deletions examples/notifications.rs
Original file line number Diff line number Diff line change
@@ -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);
}
6 changes: 6 additions & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<F>(name: &str, callback: F) -> Result<Client, OSStatus>
where F: FnMut(&Notification) + Send + 'static
{
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ unsafe impl<T> Send for BoxedCallback<T> {}

impl<T> Drop for BoxedCallback<T> {
fn drop(&mut self) {
unsafe {
if !self.0.is_null() {
if !self.0.is_null() {
unsafe {
let _ = Box::from_raw(self.0);
}
}
Expand Down

0 comments on commit 14eff2e

Please sign in to comment.