e_midi 0.1.0

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

e_midi - Interactive MIDI Player

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

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)

Installation

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 files 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

Development

Project Structure

├── build.rs              # MIDI processing and code generation
├── src/
│   ├── main.rs           # Main application logic
│   ├── cli.rs            # Command-line interface
│   ├── tui.rs            # Terminal user interface
│   ├── lib.rs            # Library exports
│   ├── ipc/              # Inter-process communication
│   │   ├── mod.rs        # IPC module exports
│   │   ├── events.rs     # Event definitions
│   │   ├── publisher.rs  # Event publishing
│   │   ├── subscriber.rs # Event subscription
│   │   ├── service.rs    # Service management
│   │   └── types.rs      # Type definitions
│   └── midi_data.rs      # Generated MIDI data (build artifact)
├── midi/                 # Static MIDI files (compiled in)
│   ├── *.mid            # Classical and other MIDI files
│   ├── attic/           # Archive of various MIDI files
│   └── good/            # Curated high-quality files
├── Cargo.toml           # Dependencies and metadata
└── examples/            # Usage examples

Adding Features

The codebase is modular and easy to extend:

  • New playback modes: Add functions in main.rs
  • Additional MIDI processing: Modify build.rs
  • Enhanced UI: Extend the menu system or TUI components
  • CLI extensions: Add new subcommands or options in cli.rs
  • IPC events: Extend event types in ipc/events.rs
  • Export capabilities: Add file output options

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

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

Changelog

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