forked from processing/libprocessing
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlib.rs
More file actions
109 lines (91 loc) · 2.93 KB
/
lib.rs
File metadata and controls
109 lines (91 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use bevy::prelude::*;
use bevy_midi::prelude::*;
use processing_core::app_mut;
use processing_core::error::{self, Result};
pub struct MidiPlugin;
pub const NOTE_ON: u8 = 0b1001_0000;
pub const NOTE_OFF: u8 = 0b1000_0000;
impl Plugin for MidiPlugin {
fn build(&self, app: &mut App) {
// TODO: Update `bevy_midi` to treat connections as entities
// in order to support hot-plugging
app.insert_resource(MidiOutputSettings {
port_name: "libprocessing output",
});
app.add_plugins(MidiOutputPlugin);
}
}
pub fn connect(In(port): In<usize>, output: Res<MidiOutput>) -> Result<()> {
match output.ports().get(port) {
Some((_, p)) => {
output.connect(p.clone());
Ok(())
}
None => Err(error::ProcessingError::MidiPortNotFound(port)),
}
}
pub fn disconnect(output: Res<MidiOutput>) -> Result<()> {
output.disconnect();
Ok(())
}
pub fn refresh_ports(output: Res<MidiOutput>) -> Result<()> {
output.refresh_ports();
Ok(())
}
pub fn list_ports(output: Res<MidiOutput>) -> Result<Vec<String>> {
Ok(output
.ports()
.iter()
.enumerate()
.map(|(i, (name, _))| format!("{}: {}", i, name))
.collect())
}
pub fn play_notes(In((note, duration)): In<(u8, u64)>, output: Res<MidiOutput>) -> Result<()> {
output.send([NOTE_ON, note, 127].into()); // Note on, channel 1, max velocity
std::thread::sleep(std::time::Duration::from_millis(duration));
output.send([NOTE_OFF, note, 127].into()); // Note off, channel 1, max velocity
Ok(())
}
#[cfg(not(target_arch = "wasm32"))]
pub fn midi_refresh_ports() -> error::Result<()> {
app_mut(|app| {
let world = app.world_mut();
world.run_system_cached(refresh_ports).unwrap()
})?;
// run the `PreUpdate` schedule to let `bevy_midi` process it's callbacks and update the ports list
// TODO: race condition is still present here in theory
app_mut(|app| {
app.world_mut().run_schedule(PreUpdate);
Ok(())
})
}
#[cfg(not(target_arch = "wasm32"))]
pub fn midi_list_ports() -> error::Result<Vec<String>> {
app_mut(|app| {
let world = app.world_mut();
world.run_system_cached(list_ports).unwrap()
})
}
#[cfg(not(target_arch = "wasm32"))]
pub fn midi_connect(port: usize) -> error::Result<()> {
app_mut(|app| {
let world = app.world_mut();
world.run_system_cached_with(connect, port).unwrap()
})
}
#[cfg(not(target_arch = "wasm32"))]
pub fn midi_disconnect() -> error::Result<()> {
app_mut(|app| {
let world = app.world_mut();
world.run_system_cached(disconnect).unwrap()
})
}
#[cfg(not(target_arch = "wasm32"))]
pub fn midi_play_notes(note: u8, duration: u64) -> error::Result<()> {
app_mut(|app| {
let world = app.world_mut();
world
.run_system_cached_with(play_notes, (note, duration))
.unwrap()
})
}