| Crates.io | mseq |
| lib.rs | mseq |
| version | 2.0.1 |
| created_at | 2024-10-10 20:42:32.764056+00 |
| updated_at | 2025-10-01 21:56:27.617507+00 |
| description | Library for developing MIDI Sequencers. |
| homepage | |
| repository | https://github.com/MF-Room/mseq |
| max_upload_size | |
| id | 1404402 |
| size | 96,758 |
mseq is a lightweight MIDI sequencer framework written in Rust. It provides a flexible core for building sequencers that can run in standalone, master, or slave mode, with synchronization over standard MIDI clock and transport messages.
Conductor] trait for defining sequencer logicTrack] traitDeteTrack]The sequencer is driven by a user-provided [Conductor] implementation, which defines how the sequencer initializes, progresses at each clock tick, and reacts to external MIDI messages.
A Conductor defines how your sequencer behaves:
Conductor::init] → called once at startup to initialize state and produce initial [Instruction]s (e.g., send program changes or reset messages).Conductor::update] → called at every clock tick to advance the sequencer state and emit the instructions for that tick (e.g., note on/off events).Conductor::handle_input] → called when a new [MidiMessage] arrives, allowing the conductor to react to external inputs in real time.Sequencers can also be built around the [Track] trait, which provides a simple interface for describing step-based musical patterns. Each track produces a set of [Instruction]s at a given step.
The provided [DeteTrack] implements a deterministic looping track:
use mseq::{Track, DeteTrack, Instruction};
let mut track = DeteTrack::default();
// On each tick, play the instructions for the current step
let instructions: Vec<Instruction> = track.play_step(step);
This makes it easy to implement custom track types, from simple step sequencers to more complex algorithmic patterns.
The entry point of the crate is the [run] function:
use mseq::{run, Conductor, Context, Instruction, MidiMessage};
struct MyConductor;
impl Conductor for MyConductor {
fn init(&mut self, _ctx: &mut Context) -> Vec<Instruction> {
vec![]
}
fn update(&mut self, _ctx: &mut Context) -> Vec<Instruction> {
vec![]
}
fn handle_input(&mut self, input: MidiMessage, _ctx: &Context) -> Vec<Instruction> {
vec![]
}
}
fn main() -> Result<(), mseq::MSeqError> {
let conductor = MyConductor;
let out_port = None;
let midi_in = None;
run(conductor, out_port, midi_in)
}
You can find ready-to-run examples in the examples directory. directory. They demonstrate various usage patterns, from simple standalone sequencers to multi-track setups.