High-level PortMidi bindings and wrappers for Rust

Overview

portmidi-rs

Build Status Documentation

High-level PortMidi bindings for Rust.

PortMidi website: http://portmedia.sourceforge.net/portmidi/

Installation

Add this to your Cargo.toml.

[dependencies]
portmidi = "^0.2"

Prerequisites

You need to make sure you have the PortMidi library installed.

On Ubuntu / Debian:

apt-get install libportmidi-dev

Arch Linux:

pacman -S portmidi

On OSX (Homebrew):

brew install portmidi

On OSX, if you get a linker error ld: library not found for -lportmidi, either,

  • make sure you have the Xcode Command Line Tools installed, not just Xcode, or

  • make sure you have the PortMidi library in your $LIBRARY_PATH, e.g. for Homebrew:

    export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/lib"

Examples

Examples can be run by cloning the repository and running cargo run --example .

  • play: demonstrates midi output by playing Twinkle Twinkle Little Star (forever...)
  • monitor: demonstrate midi input
  • monitor-all: listens on all-input devices and uses threads and channels

Example: cargo run --example play -- 1 --verbose

Both play and monitor need a device number supplied, run them without an argument to get a list of the connected devices, e.g.

License

Licensed under either of

Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • Getting ready for rust 1.0

    Getting ready for rust 1.0

    Rust 1.0 is on the way, so I'm thinking now would be a good time to do any refactoring and tidying up before the masses arrive.

    I'm proposing the following changes:

    • Remove time.rs: it's not required by midi.rs, maybe it belongs in it's own crate? There is rust-event which might be a more full featured solution anyway.
    • Remove util.rs: again it's not required by midi.rs, I would have though most people would be better of with collections from the std lib rather than binding to portmidi's queue library.
    • Flatten midi.rs into lib.rs: this also simplifies the API.
    • Rename variables to conform to rust guidelines
    • 0 warnings

    I'm happy to do the work, but I just want to check to see if this is the direction you'd like to go it.

    opened by samdoshi 25
  • Relicense under dual MIT/Apache-2.0

    Relicense under dual MIT/Apache-2.0

    This issue was automatically generated. Feel free to close without ceremony if you do not agree with re-licensing or if it is not possible for other reasons. Respond to @cmr with any questions or concerns, or pop over to #rust-offtopic on IRC to discuss.

    You're receiving this because someone (perhaps the project maintainer) published a crates.io package with the license as "MIT" xor "Apache-2.0" and the repository field pointing here.

    TL;DR the Rust ecosystem is largely Apache-2.0. Being available under that license is good for interoperation. The MIT license as an add-on can be nice for GPLv2 projects to use your code.

    Why?

    The MIT license requires reproducing countless copies of the same copyright header with different names in the copyright field, for every MIT library in use. The Apache license does not have this drawback. However, this is not the primary motivation for me creating these issues. The Apache license also has protections from patent trolls and an explicit contribution licensing clause. However, the Apache license is incompatible with GPLv2. This is why Rust is dual-licensed as MIT/Apache (the "primary" license being Apache, MIT only for GPLv2 compat), and doing so would be wise for this project. This also makes this crate suitable for inclusion and unrestricted sharing in the Rust standard distribution and other projects using dual MIT/Apache, such as my personal ulterior motive, the Robigalia project.

    Some ask, "Does this really apply to binary redistributions? Does MIT really require reproducing the whole thing?" I'm not a lawyer, and I can't give legal advice, but some Google Android apps include open source attributions using this interpretation. Others also agree with it. But, again, the copyright notice redistribution is not the primary motivation for the dual-licensing. It's stronger protections to licensees and better interoperation with the wider Rust ecosystem.

    How?

    To do this, get explicit approval from each contributor of copyrightable work (as not all contributions qualify for copyright, due to not being a "creative work", e.g. a typo fix) and then add the following to your README:

    ## License
    
    Licensed under either of
    
     * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
     * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
    
    at your option.
    
    ### Contribution
    
    Unless you explicitly state otherwise, any contribution intentionally submitted
    for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
    additional terms or conditions.
    

    and in your license headers, if you have them, use the following boilerplate (based on that used in Rust):

    // Copyright 2016 portmidi-rs Developers
    //
    // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
    // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
    // http://opensource.org/licenses/MIT>, at your option. This file may not be
    // copied, modified, or distributed except according to those terms.
    

    It's commonly asked whether license headers are required. I'm not comfortable making an official recommendation either way, but the Apache license recommends it in their appendix on how to use the license.

    Be sure to add the relevant LICENSE-{MIT,APACHE} files. You can copy these from the Rust repo for a plain-text version.

    And don't forget to update the license metadata in your Cargo.toml to:

    license = "MIT OR Apache-2.0"
    

    I'll be going through projects which agree to be relicensed and have approval by the necessary contributors and doing this changes, so feel free to leave the heavy lifting to me!

    Contributor checkoff

    To agree to relicensing, comment with :

    I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to chose either at their option.
    

    Or, if you're a contributor, you can check the box in this repo next to your name. My scripts will pick this exact phrase up and check your checkbox, but I'll come through and manually review this issue later as well.

    • [ ] @hansjorg
    • [x] @irh
    • [x] @musitdev
    • [x] @samdoshi
    • [x] @steveklabnik
    • [x] @suhr
    • [x] @thenyeguy
    opened by emberian 15
  • On `initialize` and `terminate`

    On `initialize` and `terminate`

    In my opinion it would be more rusty to provide a trait object with something like PortMidi::new() which implements Drop and calls portmidi::terminate when dropped. Both initalize as well as terminate should not be part of the public interface.

    opened by klingtnet 11
  • Add documentation

    Add documentation

    I've generated documentation and added the few shim files needed to make it work with github pages, but I can't make a PR into a new branch, can someone with contribute access here make a gh-pages branch to put the documentation in?

    I've got the documentation in this repo: https://github.com/porglezomp/rust-portmidi/tree/gh-pages, and here's it being hosted on github pages: https://porglezomp.github.io/rust-portmidi

    opened by porglezomp 6
  • Implement Send trait for pm::InputPort and pm::OutputPort

    Implement Send trait for pm::InputPort and pm::OutputPort

    When trying to use portmidi in a multithreaded environment, for example to implement a callback functionality, it is not possible to launch a thread and moving something into that thread that contains an InputPort or OutputPort. The error is: the trait core::marker::Send is not implemented for the type *const libc::c_void

    opened by jonas-k 4
  • Refactor

    Refactor

    I've basically rewritten the complete portmidi bindings crate and updated the examples. If you don't like the changes, don't merge it, otherwise I could use the fork as its own cargo crate. There are still somethings left todo, all in front ~~are unit tests~~ more unit tests and a wrapper for raw midi messages. I don't have much time at the moment, so this will be left as an exercise for other contributors.

    opened by klingtnet 3
  • duration API changes

    duration API changes

    Looks like the duration API was changed recently: https://github.com/rust-lang/rust/issues/16466

    In particular:

    fn milliseconds(millis: i32) -> Duration
    

    to

    fn milliseconds(milliseconds: i64) -> Duration
    
    opened by samdoshi 2
  • Add lifetimes to prevent segfault

    Add lifetimes to prevent segfault

    Sorry for the delay. As announced, the following PR adds some extra lifetime constraint, s.t. the example mentioned in #33 stops compiling. It is, however, not a waterproof solution. The library can still segfault if you create two PortMidi instances, drop one of them and continue to work with the remaining one. Fixing this would require some global state that keeps track of how many PortMidi instances are currently active.

    opened by Woyten 1
  • Add basic wrapper for sysex write

    Add basic wrapper for sysex write

    Hey, I added a wrapper for Pm_WriteSysEx. I tested it on my Novation Launchpad, and it works as intended.

    I am not very familiar with PortMidi or MIDI in general, so let me know if I am missing something important.

    I added a check for the terminator, because looking at the C code here: http://portmedia.sourceforge.net/portmidi/doxygen/portmidi_8c-source.html, it looks like PortMidi will happily write off the edge of the buffer until it hits a terminator.

    opened by jamesmunns 1
  • Implements `Send` for ports

    Implements `Send` for ports

    I've implemented the Send marker trait for the in- and output ports so they can be moved between threads. I've (re-)wrote a test and added an example that uses threads and channels to monitors all available input ports.

    opened by klingtnet 1
  • Fix documentation

    Fix documentation

    It seems as though the documentation on rust-ci is no longer updating: http://www.rust-ci.org/musitdev/rust-portmidi I think quite a lot of people are having similar problems.

    I'm using the following script to manually upload the docs to gh-pages for my midi crate: https://github.com/samdoshi/midi-rs/blob/master/other/update-gh-pages.sh

    It uses https://github.com/davisp/ghp-import which is available via pypi or apt.

    opened by samdoshi 1
  • Some code is unsafe but not marked as unsafe

    Some code is unsafe but not marked as unsafe

    This example segfaults:

    let output_port = {
        let context = PortMidi::new().unwrap();
        let device = context.device(device_number).unwrap();
        context.output_port(device, 1024).unwrap()
    };
    
    output_port.write_message(message); // SEGFAULT
    

    The problem is that output_port outlives context. To be more precise, context calls Pm_Terminate in its destructor rendering output_port invalid. But, unfortunately, outport_port is still accessible after the scope braces. The problem can be solved by adding an artificial lifetime to the DeviceInfo struct, s.t. Rust knows that output_port depends on a DeviceInfo instance which depends on context. Also, DeviceInfo::new should be unsafe and PortMidi::device should validate the device number.

    opened by Woyten 7
  • Running examples without arguments

    Running examples without arguments

    Running cargo run --example play or cargo run --example monitor on master with no arguments displays this error:

    Invalid arguments. Usage: play [-v | --verbose] error: Process didn't exit successfully: target/debug/examples/play (exit code: 1)

    Did I miss something?

    opened by rap2hpoutre 11
  • Basic SysEx support

    Basic SysEx support

    I'm trying to do some SysEx stuff, but it requires a binding for Pm_WriteSysEx and needs to be able to read the full 32 bits that is written to the buffer by the portmidi C library. Is this possible?

    opened by smosher 6
Owner
Philippe Delrieu
Philippe Delrieu
A high-level Rust crate around the Discord API, aimed to be easy and straight-forward to use.

rs-cord A high-level Rust crate around the Discord API, aimed to be easy and straight-forward to use. Documentation • Crates.io • Discord Navigation M

Jay3332 4 Sep 24, 2022
This crate provides a convenient macro that allows you to generate type wrappers that promise to always uphold arbitrary invariants that you specified.

prae This crate provides a convenient macro that allows you to generate type wrappers that promise to always uphold arbitrary invariants that you spec

null 96 Dec 4, 2022
Runit service management wrappers

void-svtools Basic wrappers for managing services for runit,

Isaac Hung 1 Aug 3, 2022
A collection of compilers based around compiling a high level language to a Brainfuck dialect.

tf A collection of compilers based around compiling a high level language to a Brainfuck dialect. Built at, and for, the VolHacks V hackathon during O

adam mcdaniel 6 Nov 25, 2021
An upper-level course for CS majors on formal languages theory and compilers.

CS4100 Introduction to Formal Languages and Compilers Spring 2022 An upper-level course for CS majors on formal languages theory and compilers. Topics

null 2 May 28, 2022
Simple tray application which shows battery level for HyperX Cloud Flight Wireless Headset.

HyperX Cloud Flight Battery Monitoring Introduction Simple tray application which shows battery level for HyperX Cloud Flight Wireless Headset. Screen

Stefan Kondinski 18 Dec 27, 2022
A toy-level BLE peripheral stack

bleps - A toy-level BLE peripheral stack This is a BLE peripheral stack in Rust. (no-std / no-alloc) To use it you need an implementation of embedded-

Björn Quentin 4 Oct 17, 2022
Rust bindings to Cloudflare Worker KV Stores using wasm-bindgen and js-sys.

worker-kv Rust bindings to Cloudflare Worker KV Stores using wasm-bindgen and js-sys

Zeb Piasecki 39 Dec 4, 2022
Damavand is a quantum circuit simulator. It can run on laptops or High Performance Computing architectures, such CPU distributed architectures or multi GPU distributed architectures.

Damavand is a quantum circuit simulator. It can run on laptops or High Performance Computing architectures, such CPU distributed architectures or multi GPU distributed architectures.

MichelNowak 0 Mar 29, 2022
Moonshine CSS - 🥃 High-proof atomic CSS framework

Moonshine CSS - ?? High-proof atomic CSS framework

Econify 25 Nov 25, 2022
Rust bindings for the WebView2 COM APIs

webview2-rs Rust bindings for the WebView2 COM APIs Crates in this repo The root of this repo defines a virtual workspace in Cargo.toml which includes

Bill Avery 24 Dec 15, 2022
Rust bindings for the KING OF TIME API

Rust bindings for the KING OF TIME API Example Prints if you are at work or not at work. $ cargo run --example tc -- status Record the time you start

Idein Inc. 2 Oct 11, 2021
Rust bindings for the Mattermost API

mattermost_api Rust bindings for the Mattermost API Installing Add the latest version to your Cargo.toml. Using Docs link. Developing Building Require

Matt Boulanger 1 Feb 2, 2022
Rust bindings for libjuice. Look at datachannel-rs if you need more batteries.

Rust bindings for libjuice. Look at datachannel-rs if you need more batteries.

Vyacheslav S. Troshin 3 Sep 25, 2022
GGML bindings that aim to be idiomatic Rust rather than directly corresponding to the C/C++ interface

rusty-ggml GGML bindings that aim to be idiomatic Rust rather than directly corresponding to the C/C++ interface. GG-what? See: https://github.com/gge

Kerfuffle 6 May 16, 2023
Unofficial python bindings for the rust llm library. 🐍❤️🦀

llm-rs-python: Python Bindings for Rust's llm Library Welcome to llm-rs, an unofficial Python interface for the Rust-based llm library, made possible

Lukas Kreussel 7 May 20, 2023
Rust bindings to llama.cpp, using metal on macOS

llama-rs Rust bindings to llama.cpp, for macOS, with metal support, for testing and evaluating whether it would be worthwhile to run an Llama model lo

Max Brunsfeld 7 Aug 31, 2023
A Rust proc-macro crate which derives functions to compile and parse back enums and structs to and from a bytecode representation

Bytecode A simple way to derive bytecode for you Enums and Structs. What is this This is a crate that provides a proc macro which will derive bytecode

null 4 Sep 3, 2022
A stupid macro that compiles and executes Rust and spits the output directly into your Rust code

inline-rust This is a stupid macro inspired by inline-python that compiles and executes Rust and spits the output directly into your Rust code. There

William 19 Nov 29, 2022