## MIDI Gate This plugin demonstrates: * Receiving MIDI input * Processing audio based on MIDI events with sample accuracy * Supporting MIDI programs which the host can control/automate, or present a user interface for with human readable labels A key concept of LV2 that is introduced with this plugin is URID. As you've learned before, many things in the LV2 ecosystem are identified by URIs. However, comparing URIs isn't nescessarily fast and the time it takes to compare URIs rises with their length. Therefore, every known URI is mapped to number, a so-called URID, which is used instead of the full URI when time and space is valuable. This mapping is done by the host, which also assures that the mappings are consistent across plugins. Therefore, URIDs are also used for host-plugin or plugin-plugin communication. ### midigate/eg-midigate-rs.lv2/manifest.ttl The manifest.ttl file follows the same template as the previous example. ```ttl @prefix lv2: . @prefix rdfs: . @prefix ui: . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . ``` ### midigate/eg-midigate-rs.lv2/midigate.ttl The same set of namespace prefixes with two additions for LV2 extensions this plugin uses: atom and urid. ```ttl @prefix atom: . @prefix doap: . @prefix lv2: . @prefix midi: . @prefix rdfs: . @prefix urid: . a lv2:Plugin ; doap:name "Example MIDI Gate (Rust Version)" ; doap:license ; lv2:project ; lv2:requiredFeature urid:map , lv2:inPlaceBroken ; lv2:optionalFeature lv2:hardRTCapable ; ``` This plugin has three ports. There is an audio input and output as before, as well as a new `AtomPort`. An `AtomPort` buffer contains an `Atom`, which is a generic container for any type of data. In this case, we want to receive MIDI events, so the (mandatory) `atom:bufferType` is `atom:Sequence`, which is a series of events with time stamps. Events themselves are also generic and can contain any type of data, but in this case we are only interested in MIDI events. The (optional) `atom:supports` property describes which event types are supported. Though not required, this information should always be given so the host knows what types of event it can expect the plugin to understand. The (optional) `lv2:designation` of this port is `lv2:control`, which indicates that this is the "main" control port where the host should send events it expects to configure the plugin, in this case changing the MIDI program. This is necessary since it is possible to have several MIDI input ports, though typically it is best to have one. ```ttl lv2:port [ a lv2:InputPort , atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports midi:MidiEvent ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "control" ; lv2:name "Control" ] , [ a lv2:AudioPort , lv2:InputPort ; lv2:index 1 ; lv2:symbol "in" ; lv2:name "In" ] , [ a lv2:AudioPort , lv2:OutputPort ; lv2:index 2 ; lv2:symbol "out" ; lv2:name "Out" ] . ``` ### midigate/Cargo.toml The `Cargo.toml` file is pretty similiar too. This plugin needs no extra features, but it needs the `wmidi` crate, which provides the enums to handle MIDI messages. ```toml [package] name = "midigate" version = "0.1.0" authors = ["Jan-Oliver 'Janonard' Opdenhövel "] edition = "2018" [lib] crate-type = ["cdylib"] [dependencies] wmidi = "3.1.0" lv2 = "0.6.0" ``` ### midigate/src/lib.rs Use the prelude and the `wmidi` crate. ```rs use lv2::prelude::*; use wmidi::*; #[derive(PortCollection)] pub struct Ports { control: InputPort, input: InputPort