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
Running
Usage
Interactive Menu
The application starts with an interactive configuration menu:
- Loop Configuration: Choose playlist and/or individual song looping
- Delay Settings: Configure pause duration between songs
- 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
# Play song at index 5
# Play song 3 with custom tempo
# Play specific tracks (1, 3, 5) from song 2
# Play all songs in sequence
# Play songs in random order
Looping and Timing
# Loop the entire playlist
# Loop individual songs with 5-second delays
# Play song 0 on loop
Scan Mode
# Sequential scan with default 30-second segments
# Random position scan with 45-second segments
# Progressive scan (increasing duration)
# Scan with random start positions
Dynamic Playlist Management
# Add individual MIDI files
# Scan directory for MIDI files
# List only dynamically loaded songs
# Clear all dynamic songs
TUI Mode
# Launch with Terminal User Interface
# TUI with pre-loaded dynamic songs
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
# Scan all songs for 10 seconds each
Scripting
#!/bin/bash
# Play random songs for background music with 2-second delays
while ; do
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 bybuild.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 operationsmidly: MIDI file parsingrimd: Additional MIDI utilitiesansi_term: Terminal color outputiceoryx2: Lock-free inter-process communicationratatui: Terminal user interface frameworkcrossterm: 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:
- Ensure all MIDI files are valid
- Check that dependencies are up to date:
cargo update - 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
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- 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