Skip to content

Commit

Permalink
Merge pull request #2 from l0calh05t/midi
Browse files Browse the repository at this point in the history
Add bindings for `libraries/Midi/Midi_c.h`
  • Loading branch information
andrewcsmith committed Jul 14, 2021
2 parents a335c18 + bb595b8 commit 02cfc9f
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

.vscode
**/*.rs.bk
Cargo.lock
target/
11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@ links = "bela"

[build-dependencies]
bindgen = "0.58"
cc = { version = "1.0", optional = true }

[dev-dependencies]
libc = "0.2"
nix = "0.21"
nix = "0.22"

[features]
static = []
midi = [ "cc" ]

[[example]]
name = "hello"

[[example]]
name = "midi"
required-features = [ "midi" ]
35 changes: 35 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,39 @@ fn main() {
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings");

#[cfg(feature = "midi")]
{
let midi_root = bela_root.join("root/Bela/libraries/Midi");

// TODO: asound is in usr/lib/arm-linux-gnueabihf, so copy it to OUT_DIR,
// as otherwise the link step will also find libpthread.so and other link
// scripts there which reference absolute paths. Is there a cleaner
// solution?
let asound_lib = bela_root.join("usr/lib/arm-linux-gnueabihf/libasound.so");
let asound_copy = out_path.join("libasound.so");
if !asound_copy.exists() {
std::fs::copy(asound_lib, asound_copy).unwrap();
}

cc::Build::new()
.cpp(true)
.object(midi_root.join("build/Midi_c.o"))
.object(midi_root.join("build/Midi.o"))
.compile("midi");
println!("cargo:rustc-link-lib=asound");
println!("cargo:rustc-link-lib=modechk");

let midi_h = midi_root.join("Midi_c.h");
let bindings = bindgen::Builder::default()
.header(midi_h.to_str().unwrap())
.clang_arg(format!("--sysroot={}", bela_root.to_str().unwrap()))
.clang_arg(format!("-I{}", bela_include.to_str().unwrap()))
.allowlist_function("Midi_.*")
.generate()
.expect("Unable to generate bindings");
bindings
.write_to_file(out_path.join("midi_bindings.rs"))
.expect("Couldn't write bindings");
}
}
23 changes: 12 additions & 11 deletions examples/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! ssh root@bela.local "LD_LIBRARY_PATH=/root/Bela/lib /root/hello"
//! ```
//!

extern crate bela_sys;
extern crate libc;
extern crate nix;
Expand All @@ -19,22 +20,22 @@ use std::{mem, ptr, slice, thread, time};

static mut FRAME_INDEX: usize = 0;

#[no_mangle]
pub unsafe extern "C" fn render(context: *mut BelaContext, _user_data: *mut std::os::raw::c_void) {
let n_frames = (*context).audioFrames;
let n_channels = (*context).audioOutChannels;
extern "C" fn render(context: *mut BelaContext, _user_data: *mut std::os::raw::c_void) {
let context = unsafe { &mut *context };
let n_frames = context.audioFrames;
let n_channels = context.audioOutChannels;

let audio_out: &mut [f32] =
unsafe { slice::from_raw_parts_mut(context.audioOut, (n_frames * n_channels) as usize) };

let audio_out: &mut [f32] = slice::from_raw_parts_mut(
(*context).audioOut as *mut f32,
(n_frames * n_channels) as usize,
);
let frame_index = unsafe { &mut FRAME_INDEX };

let len = audio_out.len();
for (idx, samp) in audio_out.iter_mut().enumerate() {
*samp = (idx as f32 / len as f32) * (FRAME_INDEX % 5) as f32;
*samp = (idx as f32 / len as f32) * (*frame_index % 5) as f32;
}

FRAME_INDEX += 1;
*frame_index += 1;
}

extern "C" fn signal_handler(_signal: std::os::raw::c_int) {
Expand Down Expand Up @@ -77,7 +78,7 @@ fn main() {
signal::sigaction(signal::SIGINT, &sig_action).unwrap();
signal::sigaction(signal::SIGTERM, &sig_action).unwrap();

while bela_sys::Bela_stopRequested() != 0 {
while bela_sys::Bela_stopRequested() == 0 {
thread::sleep(time::Duration::new(1, 0));
}

Expand Down
95 changes: 95 additions & 0 deletions examples/midi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//! Very basic program to test MIDI bindings of the Bela

extern crate bela_sys;
extern crate libc;
extern crate nix;

use bela_sys::midi::*;
use bela_sys::{BelaContext, BelaInitSettings};
use nix::sys::signal;
use std::{mem, ptr, thread, time};

static mut MIDI: *mut Midi = ptr::null_mut();

extern "C" fn setup(_context: *mut BelaContext, _user_data: *mut std::os::raw::c_void) -> bool {
unsafe {
assert!(MIDI.is_null());
MIDI = Midi_new(b"hw:0,0,0\0".as_ptr());
}
true
}

extern "C" fn cleanup(_context: *mut BelaContext, _user_data: *mut std::os::raw::c_void) {
unsafe {
Midi_delete(MIDI);
MIDI = ptr::null_mut();
}
}

extern "C" fn render(_context: *mut BelaContext, _user_data: *mut std::os::raw::c_void) {
unsafe {
if MIDI.is_null() {
return;
}

while Midi_availableMessages(MIDI) > 0 {
let mut msg_buf = [0u8; 3];
let msg_len = Midi_getMessage(MIDI, msg_buf.as_mut_ptr()) as usize;
assert!(msg_len <= 3);
if msg_len != 0 && (msg_buf[0] & 0b1111_0000) == 0b1001_0000 {
bela_sys::rt_printf(b"Note on\n\0".as_ptr());
}
}
}
}

extern "C" fn signal_handler(_signal: std::os::raw::c_int) {
unsafe {
bela_sys::Bela_requestStop();
}
}

fn main() {
unsafe {
let mut settings = {
let mut settings: mem::MaybeUninit<BelaInitSettings> = mem::MaybeUninit::uninit();
bela_sys::Bela_defaultSettings(settings.as_mut_ptr());
settings.assume_init()
};
bela_sys::Bela_setVerboseLevel(1);
settings.setup = Some(setup);
settings.render = Some(render);
settings.cleanup = Some(cleanup);
settings.verbose = 1;
settings.highPerformanceMode = 1;
settings.analogOutputsPersist = 0;
settings.uniformSampleRate = 1;

if bela_sys::Bela_initAudio(&mut settings, ptr::null_mut()) != 0 {
println!("settings.render: {:?}", &settings.render);
panic!("lol fail");
}

if bela_sys::Bela_startAudio() != 0 {
println!("Unable to start real-time audio");
bela_sys::Bela_stopAudio();
bela_sys::Bela_cleanupAudio();
panic!("Aborting");
}

let handler = signal::SigHandler::Handler(signal_handler);
let flags = signal::SaFlags::empty();
let set = signal::SigSet::empty();
let sig_action = signal::SigAction::new(handler, flags, set);

signal::sigaction(signal::SIGINT, &sig_action).unwrap();
signal::sigaction(signal::SIGTERM, &sig_action).unwrap();

while bela_sys::Bela_stopRequested() == 0 {
thread::sleep(time::Duration::new(1, 0));
}

bela_sys::Bela_stopAudio();
bela_sys::Bela_cleanupAudio();
}
}
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

#[cfg(feature = "midi")]
pub mod midi {
include!(concat!(env!("OUT_DIR"), "/midi_bindings.rs"));
}

0 comments on commit 02cfc9f

Please sign in to comment.