e_midi

Crates.ioe_midi
lib.rse_midi
version0.1.11
created_at2025-06-20 01:52:00.091465+00
updated_at2025-07-10 02:49:48.946658+00
descriptionAn interactive/CLI/library MIDI player with advanced playback options, looping, and scan modes.
homepagehttps://github.com/davehorner/e_midi/
repositoryhttps://github.com/davehorner/e_midi/
max_upload_size
id1719036
size455,234
David Horner (davehorner)

documentation

README

e_midi - Interactive MIDI Player

e_midi is more than a simple midi player. It currently supports .mid and .xml files. MusicXML support is very alpha and if you're interested, PRs are welcome!

now includes .ogg and .mp3 embedding/playing via rodio. mp4/webm embed but do not play yet.

Features

🎵 Playback Modes

  • Single Song: Play a specific track with optional looping
  • All Songs: Play through your entire MIDI collection
  • Random Song: Randomly select and play a track
  • Scan Mode: Preview segments of songs with multiple scan patterns

🔄 Looping Options

  • Playlist Looping: Continuously loop through all songs
  • Individual Song Looping: Repeat single tracks indefinitely
  • User Control: Press 'q' + Enter during playback to quit loops

🎛️ Advanced Features

  • Track Selection: Choose specific MIDI tracks to play
  • BPM Override: Override default tempo with custom BPM
  • Configurable Delays: Set custom delays between songs (including zero delay)
  • Progress Reporting: Real-time progress display with timestamps and percentages
  • Multiple Scan Modes: Sequential, random start, and progressive scanning

🎯 Scan Mode Options

  • Sequential Scan: Play segments from each song in order

  • Random Start Scan: Begin each song segment at a random position

  • Progressive Scan: Gradually increase segment duration for deeper exploration

  • Configurable Duration: Set custom scan segment lengths (default: 30 seconds)

Additional Binary:

  • e_midi_demo01: Windows-only demo for window focus, resize, and move event integration with e_grid IPC. Useful for testing advanced window event handling and IPC features. Source: examples/demo_focus_resize_move.rs.

To run:

cargo run --bin e_midi_demo01

or after building:

target\release\e_midi_demo01.exe

Running after install:

After installing with:

cargo install e_midi

you can run the main player binary directly as e_midi from your terminal or command prompt. e_midi_demo01 is also installed and should be available for your use.

Note: The default e_midi binary/lib includes the curated MIDI sound effects from the midi folder within the repository, embedded at build time. These static songs are always available, even if you run the binary outside the repository directory.

A feature-rich, interactive MIDI player written in Rust with advanced playback options, looping capabilities, and scan modes.

  • e_midi_demo02: Persistent IPC event listener demo. Launches e_midi to play song 0 with IPC enabled, then displays all incoming MIDI note events in real time. Remains running and will display events from any e_midi instance with IPC enabled. Useful for debugging and monitoring event flow. Source: examples/e_midi_demo02.rs.
  • e_midi_ipc_player: Designed to be controlled entirely via inter-process communication. Tt listens for IPC midi events and plays the notes with a changing random voice. run e_midi_demo02, then start as many e_midi_ipc_player as you desire; they will all play the same song.

Prerequisites

  • Rust (latest stable version)
  • A MIDI output device or software synthesizer
  • MIDI files to play

Building from Source

git clone https://github.com/davehorner/e_midi.git
cd e_midi
cargo build --release

Running

cargo run

Usage

Interactive Menu

The application starts with an interactive configuration menu:

  1. Loop Configuration: Choose playlist and/or individual song looping
  2. Delay Settings: Configure pause duration between songs
  3. Playback Mode Selection: Choose from 4 different playback modes

Song Selection

The player maintains a unified song index where:

  • Static songs (compiled-in from midi/) appear first (indexes 0-N)
  • Dynamic songs (runtime-loaded) appear after static songs (indexes N+1 onwards)
  • Song selection by index works seamlessly across both types
  • Static songs provide guaranteed availability and optimal performance

Track and BPM Selection

When playing songs, you can:

  • Track Selection: Enter track numbers (e.g., "1,3,5") or press Enter for all tracks
  • BPM Override: Enter a custom BPM or press Enter to use the MIDI's default tempo

Example Session

🎵 MIDI Player Settings
═══════════════════════
🔄 Loop the entire playlist? (y/N): y
🔄 Loop individual songs? (y/N): n
⏱️  Delay between songs in seconds (default 2, 0 for no delay): 5

🎵 Choose an option:
1: Play a specific song
2: Play all songs
3: Play random song
4: Scan mode (play portions of songs)

Select option (1-4): 4

🔍 Scan Mode Options:
1: Sequential scan (play segments in order)
2: Random start scan (random positions)
3: Progressive scan (increasing duration)

Select scan type (1-3): 3

Command Line Interface

Overview

e_midi provides both interactive and command-line modes. The CLI allows for scripting, automation, and integration with other tools.

Important: Global options must come before the subcommand (e.g., e_midi --delay-between-songs 5 play-random), while subcommand-specific options come after the subcommand (e.g., e_midi scan --mode 2 --duration 45).

Full Help Output

An interactive/CLI/library MIDI player with advanced playback options, looping, and scan modes.

Usage: e_midi.exe [OPTIONS] [COMMAND]

Commands:
  list           List all available songs
  play           Play a specific song
  play-all       Play all songs in sequence
  play-random    Play songs in random order
  scan           Scan mode - play portions of songs
  list-dynamic   List only dynamically loaded songs
  clear-dynamic  Clear all dynamically loaded songs
  interactive    Run in interactive mode (default)
  help           Print this message or the help of the given subcommand(s)

Options:
      --loop-playlist
          Loop the entire playlist continuously
      --loop-individual-songs
          Loop individual songs
      --delay-between-songs <DELAY_BETWEEN_SONGS>
          Delay between songs in seconds [default: 0]
      --scan-duration <SCAN_DURATION>
          Scan segment duration in seconds [default: 30]
      --scan-random-start
          Start scan segments at random positions
  -t, --tui
          Use TUI mode with split panels (menu + playback info)
      --add-song <ADD_SONGS>
          Add MIDI files to the dynamic playlist
      --scan-directory <SCAN_DIRECTORIES>
          Scan directories and add all MIDI files to the dynamic playlist
  -h, --help
          Print help
  -V, --version
          Print version

Command Examples

Basic Playback

# List available songs
e_midi list

# Play song at index 5
e_midi play 5

# Play song 3 with custom tempo
e_midi play 3 --tempo 140

# Play specific tracks (1, 3, 5) from song 2
e_midi play 2 --tracks 1,3,5

# Play all songs in sequence
e_midi play-all

# Play songs in random order
e_midi play-random

Looping and Timing

# Loop the entire playlist
e_midi --loop-playlist play-all

# Loop individual songs with 5-second delays
e_midi --loop-individual-songs --delay-between-songs 5 play-all

# Play song 0 on loop
e_midi --loop-individual-songs play 0

Scan Mode

# Sequential scan with default 30-second segments
e_midi scan

# Random position scan with 45-second segments
e_midi scan --mode 2 --duration 45

# Progressive scan (increasing duration)
e_midi scan --mode 3

# Scan with random start positions
e_midi --scan-random-start scan

Dynamic Playlist Management

# Add individual MIDI files
e_midi --add-song song1.mid --add-song song2.mid list

# Scan directory for MIDI files
e_midi --scan-directory /path/to/midi/files list

# List only dynamically loaded songs
e_midi list-dynamic

# Clear all dynamic songs
e_midi clear-dynamic

TUI Mode

# Launch with Terminal User Interface
e_midi --tui

# TUI with pre-loaded dynamic songs
e_midi --tui --scan-directory /path/to/midi/files

Subcommand Details

play Command

Play a specific song

Usage: e_midi.exe play [OPTIONS] <SONG_INDEX>

Arguments:
  <SONG_INDEX>  Song index to play

Options:
      --tracks <TRACKS>  Track numbers to play (comma-separated)
      --tempo <TEMPO>    Tempo in BPM
  -h, --help             Print help

scan Command

Scan mode - play portions of songs

Usage: e_midi.exe scan [OPTIONS]

Options:
      --mode <MODE>          Scan mode: 1=sequential, 2=random positions, 3=progressive [default: 1]
      --duration <DURATION>  Duration of each scan segment in seconds
  -h, --help                 Print help

Integration Examples

Batch Processing

# Play all songs with logging and 1-second delays
e_midi --delay-between-songs 1 play-all > playback.log 2>&1

# Scan all songs for 10 seconds each
e_midi --scan-duration 10 scan --mode 1

Scripting

#!/bin/bash
# Play random songs for background music with 2-second delays
while true; do
    e_midi --delay-between-songs 2 play-random
    sleep 5
done

Song Management

Static vs Dynamic Songs

The e_midi player uses a hybrid approach for managing MIDI content:

Static Songs (Compiled-In)

  • Build-time Processing: MIDI and MusicXML files (.mid, .xml, .musicxml) in the midi/ directory are processed at compile time by build.rs
  • Embedded Data: Song data is compiled directly into the executable for fast access
  • Index Priority: Static songs appear first in the song index (positions 0-N)
  • Performance: Zero I/O overhead during playback - all data is in memory
  • Use Case: Core repertoire, frequently played songs, or embedded deployments

Dynamic Songs (Runtime Loading)

  • Runtime Discovery: Additional MIDI files can be loaded at runtime from specified directories
  • Flexible Content: Add new songs without recompilation
  • Index Continuation: Dynamic songs appear after static songs in the index (positions N+1 onwards)
  • File I/O: Loaded on-demand with minimal caching
  • Use Case: Experimental content, large libraries, or user-provided files

The player seamlessly handles both types, with static songs providing guaranteed availability and performance, while dynamic songs offer flexibility for expanding the music library.

Inter-Process Communication (IPC)

iceoryx2 Integration

e_midi includes built-in IPC capabilities using the iceoryx2 framework for lock-free, zero-copy communication:

Communication Features

  • Real-time Events: Playback status, song changes, progress updates
  • Remote Control: Play, stop, pause, next/previous, tempo control via IPC
  • State Synchronization: Song lists, playback state, window management
  • Grid Integration: Future support for e_grid pattern-based control

Ecosystem Integration

  • e_grid: Pattern-based MIDI triggering and sequencing
  • State Server: Centralized state management across e_* applications
  • Multi-instance: Multiple e_midi instances can coordinate playback
  • External Control: Third-party applications can control playback via IPC

Event Types

  • MIDI Commands: Play, stop, pause, resume, tempo changes
  • Status Updates: Playback started/stopped, song changes, progress
  • System Events: Heartbeats, shutdown coordination, state requests

The IPC system enables e_midi to function as both a standalone player and a component in larger musical ecosystems.

Configuration

Build-time Configuration

The application processes MIDI files at build time using build.rs. Place your MIDI files in the project directory and they will be automatically processed and embedded.

Runtime Configuration

  • Loop Settings: Configure at startup
  • Scan Duration: Default 30 seconds, configurable per session
  • Delay Between Songs: 0-∞ seconds, configurable
  • Track Selection: Per-song basis during playback

Technical Details

Architecture

  • Build Script: Processes MIDI files and generates Rust code at compile time
  • Event Timeline: Converts MIDI events to a timeline-based playback system
  • Non-blocking Input: Allows user interaction during playback
  • Accurate Timing: Precise millisecond-level timing for faithful MIDI reproduction
  • IPC Layer: iceoryx2-based inter-process communication for ecosystem integration
  • Hybrid Storage: Compile-time embedded songs + runtime dynamic loading

MIDI Processing

  • Supports standard MIDI files (SMF)
  • Handles multiple tracks and channels
  • Preserves original timing and velocity information
  • Automatic tempo calculation and BPM override support

Dependencies

  • midir: MIDI I/O operations
  • midly: MIDI file parsing
  • rimd: Additional MIDI utilities
  • ansi_term: Terminal color output
  • iceoryx2: Lock-free inter-process communication
  • ratatui: Terminal user interface framework
  • crossterm: Cross-platform terminal manipulation

Troubleshooting

No MIDI Output

Ensure you have a MIDI output device available:

  • Windows: Built-in software synthesizer or external MIDI device
  • macOS: Built-in audio or external MIDI interface
  • Linux: ALSA, JACK, or PulseAudio MIDI support

Build Issues

If you encounter build errors:

  1. Ensure all MIDI files are valid
  2. Check that dependencies are up to date: cargo update
  3. Clean and rebuild: cargo clean && cargo build

Playback Issues

  • No sound: Verify MIDI output device and volume settings
  • Timing issues: Check system audio latency settings
  • Crash during playback: Ensure MIDI files are not corrupted

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Built with the excellent Rust MIDI ecosystem
  • Inspired by classic MIDI sequencers and players
  • Thanks to the Rust community for amazing crates and documentation

Free/Public Domain MIDI Sound Effects

The midi folder contains a curated set of short, expressive MIDI sound effects (e.g., success, error, alert, coin, powerup) created by David Horner with the assistance of ChatGPT. All files listed in README.MIDI.md are released into the public domain under CC0 1.0 Universal. You may use, modify, and distribute these files freely, even for commercial purposes, without attribution.

The midi folder supports both MIDI (.mid) and MusicXML (.xml, .musicxml) files for static, compiled-in songs.

For details and a full index of available sounds, see README.MIDI.md.

Changelog

v0.1.8

  • Added initial integration with tidalcycles-rs for pattern-based MIDI sequencing and experimental live coding support. This enables advanced rhythmic and melodic pattern playback alongside standard MIDI features.

v0.1.7

  • Added e_midi_demo02 and e_midi_ipc_player binaries for IPC event monitoring and playback

v0.1.0 (Current)

  • Initial release with comprehensive MIDI playback capabilities
  • Complete CLI interface with all interactive features
  • Interactive Menu Mode with configuration options
  • Terminal User Interface (TUI) mode with --tui flag
  • Multiple Playback Modes: Single song, all songs, random, and scan modes
  • Advanced Scan Modes: Sequential, random start, and progressive scanning
  • Looping Support: Playlist and individual song looping with user control
  • Track Selection: Choose specific MIDI tracks to play
  • BPM Override: Custom tempo control with real-time adjustment
  • Dynamic Playlist Management: --add-song and --scan-directory options
  • Static vs Dynamic Songs: Compile-time embedded + runtime loading
  • Configurable Delays: Custom timing between songs (including zero delay)
  • Progress Reporting: Real-time progress with timestamps and percentages
  • Inter-process Communication (IPC): iceoryx2-based ecosystem integration
  • Cross-platform MIDI Support: Windows, macOS, and Linux compatibility
Commit count: 17

cargo fmt