{"id":16737676,"url":"https://github.com/wvengen/rmididings","last_synced_at":"2025-07-21T15:02:32.056Z","repository":{"id":57661053,"uuid":"375793861","full_name":"wvengen/rmididings","owner":"wvengen","description":"A MIDI router/processor on Rust","archived":false,"fork":false,"pushed_at":"2021-07-02T15:09:01.000Z","size":154,"stargazers_count":4,"open_issues_count":5,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-27T04:04:59.090Z","etag":null,"topics":["filters","midi","mididings","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wvengen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-10T18:31:40.000Z","updated_at":"2024-10-11T09:59:56.000Z","dependencies_parsed_at":"2022-09-26T20:31:02.518Z","dependency_job_id":null,"html_url":"https://github.com/wvengen/rmididings","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/wvengen/rmididings","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wvengen%2Frmididings","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wvengen%2Frmididings/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wvengen%2Frmididings/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wvengen%2Frmididings/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wvengen","download_url":"https://codeload.github.com/wvengen/rmididings/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wvengen%2Frmididings/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266324292,"owners_count":23911226,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-21T11:47:31.412Z","response_time":64,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["filters","midi","mididings","rust"],"created_at":"2024-10-13T00:27:26.954Z","updated_at":"2025-07-21T15:02:32.025Z","avatar_url":"https://github.com/wvengen.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RMididings\n\n[![](https://img.shields.io/crates/v/rmididings.svg)](https://crates.io/crates/rmididings)\n\nRMididings is a partial clone of [mididings](http://das.nasophon.de/mididings/)\nin [Rust](https://www.rust-lang.org/), allowing one to use a syntax not unlike\nmididings for MIDI event routing and processing. Mididings is a Python-based\nMIDI router and processor.\n\nIt is in somewhat early development, and many things are not available. What is:\n- `NoteOn`, `NoteOff`, `Ctrl` and `SysEx` events.\n- Supports the `alsa` backend, which ties it to Linux.\n- A limited set of filters, modifiers and generators.\n- A limited set of connections: `Chain!`, `Fork!` and `Not!`.\n- Scenes and subscenes, scene switching and running a single patch.\n- Pre, post, init, exit and control patches.\n- (new) native `Osc` events, which can be handled in a patch.\n\nSome missing things can be implemented, but there are some limitations using Rust,\ne.g. syntax can differ, and not all variations of argument types to filters etc.\nare supported. Sometimes the syntax is a bit messy (e.g. with `Process`). We'll see\nwhat can be improved.\n\n## Running\n\nYou'll need [Rust](https://www.rust-lang.org/) 1.52.0+ with [Cargo](https://doc.rust-lang.org/cargo/).\nThe easiest option to get a recent enough Rust is using [Rustup](https://rustup.rs/).\n\nYou also need the ALSA headers. On Debian you would need to run `apt-get install libasound2-dev`,\non Fedora `dnf install alsa-lib-devel`.\n\nRmididings is a crate, which means that you write your own program that uses it. Let's start with a\nsimple example. Create a project directory, and a subdirectory `src`, where you put the following file\nas `main.rs`:\n\n```rust\n// src/main.rs\n#[macro_use]\nextern crate rmididings;\nuse rmididings::*;\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n  let mut md = RMididings::new()?;\n\n  md.config(ConfigArguments {\n    in_ports:  \u0026[[\"input\",  \"Virtual Keyboard:Virtual Keyboard\"]],\n    out_ports: \u0026[[\"output\", \"midisnoop:MIDI Input\"]],\n    ..ConfigArguments::default()\n  })?;\n\n  md.run(RunArguments {\n    patch: \u0026Pass(),\n    ..RunArguments::default()\n  })?;\n\n  Ok(())\n}\n```\n\nTo get this running, you'll also need a `Cargo.toml` in the project directory:\n\n```\n[package]\nname = \"myproject\"\nversion = \"0.0.1\"\n\n[dependencies]\nrmididings = \"^0.2.1\"\n```\n\nThen, from within the project directory, run `cargo run`, and you're set. This sample\nprogram passes all events from the input to the output port. When before running you\nhave [vkeybd](https://github.com/tiwai/vkeybd) and [midisnoop](https://github.com/surfacepatterns/midisnoop)\nrunning (same package names in Debian/Ubuntu), they will be connected automatically.\nTerminate the program with \u003ckbd\u003eCtrl-C\u003c/kbd\u003e\n\n## Building a patch\n\nThe patch above merely passes all events with `Pass()`. It becomes more interesting when\nwe start building a chain of filters. Instead of `\u0026Pass()`, we could use the following:\n\n```\n\u0026Chain!(\n  ChannelFilter(1),\n  Fork!(\n    Pass(),\n    Chain!(Transpose(4), VelocityMultiply(0.8)),\n    Chain!(Transpose(7), VelocityMultiply(0.5))\n  ),\n  Channel(2)\n)\n```\n\nThis chain ignores any other channel than 1 and returns a major chord for the note, with\nhigher notes slightly attenuated. Finally all notes are sent out at channel 2.\n\n## Scenes\n\nInstead of a patch, one can pass `scenes` to the `run` function:\n\n```rust\nmd.run(RunArguments {\n    scenes: \u0026[\n        // Scene 1\n        \u0026Scene {\n            name: \"Run\",\n            patch: \u0026Pass(),\n            ..Scene::default()\n        },\n        // Scene 2\n        \u0026Scene {\n            name: \"Pause\",\n            patch: \u0026Discard(),\n            ..Scene::default()\n        }\n    ],\n    control: \u0026Fork!(\n      Chain!(TypeFilter!(Note), KeyFilter(62), SceneSwitch(2)),\n      Chain!(TypeFilter!(Note), KeyFilter(60), SceneSwitch(1))\n    ),\n    ..RunArguments::default()\n})?;\n```\n\nHere there are two scenes, one that passes all events and one that discards them.\nThe `control` patch is always run, here the note central C and the following D are used\nto switch between the scenes.\n\n## Plans\n\nSee [issues](https://github.com/wvengen/rmididings/issues).\n\n## License\n\n[GPL-3.0 or later](LICENSE.md) or later.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwvengen%2Frmididings","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwvengen%2Frmididings","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwvengen%2Frmididings/lists"}