Skip to content

Commit

Permalink
lift 'Sync' restriction
Browse files Browse the repository at this point in the history
  • Loading branch information
valsteen committed Jan 13, 2024
1 parent 7392a3e commit 28de3d7
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 15 deletions.
9 changes: 4 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ mod runloop;
use crate::runloop::{start_notification_loop, Callback};
use coremidi::Client;
use once_cell::sync::OnceCell;
use std::error::Error;
use std::sync::PoisonError;
use std::{error::Error, sync::PoisonError};

pub(crate) static DEVICE_UPDATE_TX: OnceCell<Callback> = OnceCell::new();

fn handle_device_updates<T: Fn() + Send + Sync + 'static>(
fn handle_device_updates<T: Fn() + Send + 'static>(
device_update: T,
get_client: bool,
) -> Result<Option<Client>, Box<dyn Error + Send + Sync + 'static>> {
Expand Down Expand Up @@ -40,7 +39,7 @@ fn handle_device_updates<T: Fn() + Send + Sync + 'static>(
/// This can happen if `MIDIClientCreate` was called before `receive_device_updates`, which sets the thread for receiving
/// such notification from the OS. This would mean `midir::MidiInput::new` or similar would have been called before
/// calling `receive_device_updates`.
pub fn receive_device_updates<T: Fn() + Send + Sync + 'static>(
pub fn receive_device_updates<T: Fn() + Send + 'static>(
device_update: T,
) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
handle_device_updates(device_update, false)?;
Expand All @@ -54,7 +53,7 @@ pub fn receive_device_updates<T: Fn() + Send + Sync + 'static>(
/// same as `receive_device_updates`, may additionally fail if any of `get_client_and_receive_device_updates` or
/// `receive_device_updates` was already called, because the client can only be obtained the first time the loop
/// is run.
pub fn get_client_and_receive_device_updates<T: Fn() + Send + Sync + 'static>(
pub fn get_client_and_receive_device_updates<T: Fn() + Send + 'static>(
device_update: T,
) -> Result<Client, Box<dyn Error + Send + Sync + 'static>> {
handle_device_updates(device_update, true)?.ok_or_else(|| "Client was already initialized".into())
Expand Down
23 changes: 13 additions & 10 deletions src/runloop.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
use std::error::Error;
use std::sync::mpsc::{channel, sync_channel};
use std::sync::{Arc, Mutex, PoisonError};
use std::{
error::Error,
sync::{
mpsc::{channel, sync_channel},
Arc, Mutex, PoisonError,
},
};

use core_foundation::base::OSStatus;
use std::thread;
use std::time::Duration;
use std::{thread, time::Duration};

use core_foundation::runloop::CFRunLoop;
use coremidi::{Client, Notification, Sources};
use log::{error, info};

static SANITY_CHECK_ERROR: &str = "MIDIClientCreate was called before receive_device_updates. \
This often occurs when using midir::MidiInput::new, which prematurely sets the thread \
for receiving MIDI device notifications.";
static SANITY_CHECK_ERROR: &str = "MIDIClientCreate was called before receive_device_updates. This often occurs when \
using midir::MidiInput::new, which prematurely sets the thread for receiving MIDI \
device notifications.";

static VIRTUAL_DEVICE_NAME: &str = "device-detection-virtual-device";
static CLIENT_DEVICE_NAME: &str = "device-detection-client";

static CHANNEL_PANIC_MESSAGE: &str = "unable to communicate between notifier and main thread";

pub(crate) type Callback = Arc<Mutex<Option<Box<dyn Fn() + 'static + Send + Sync>>>>;
pub(crate) type Callback = Arc<Mutex<Option<Box<dyn Fn() + 'static + Send>>>>;

pub(crate) fn osstatus_error(osstatus: OSStatus) -> String {
format!("OSStatus {osstatus}")
Expand All @@ -43,7 +46,7 @@ pub(crate) fn start_notification_loop(
return_client: bool,
) -> Result<(Callback, Option<Client>), Box<dyn Error + Send + Sync + 'static>> {
let (send_new_device_notification, receive_new_device_notification) = channel();
let sanity_check_callback: Box<dyn Fn() + Send + Sync + 'static> =
let sanity_check_callback: Box<dyn Fn() + Send + 'static> =
Box::new(move || send_new_device_notification.send(()).unwrap());

let notification_callback = Arc::new(Mutex::new(Some(sanity_check_callback)));
Expand Down

0 comments on commit 28de3d7

Please sign in to comment.