Skip to main content

Daemon that maps MIDI events to system actions (Elgato, Hue, or custom functions).

Project description

🎹 PyMIDI Controller

Python License Last Commit

A lightweight Python CLI and background MIDI listener for controlling Philips Hue and Elgato Ring Lights via a MIDI device.


📚 Table of Contents

🚀 Installation

Requirements:

  • Python 3.7 or higher
  • A modern Linux distro (systemd)

Via pip

pip install pymidi-controller

Via pipx (isolated install)

pipx install pymidi-controller

If you use pipx, make sure ~/.local/bin is on your PATH (pipx ensurepath).


⚡ Quickstart

  1. Initialize your config (creates ~/.config/pymidi-controller/config.yaml):
    pymidi init
    
  2. Discover your Hue Bridge (press the link button when prompted):
    pymidi hue discover
    
  3. Discover your Elgato Ring Light:
    pymidi elgato discover
    
  4. Map MIDI inputs (listen to your controller to grab event keys):
    pymidi midi listen
    
    Press buttons/knobs to print strings like control_change:0:12:127 for use in your config.
  5. Edit your config (see Configuration) to add your device IPs, API keys, MIDI bindings, and color cycles.
  6. Start the listener to test configuration:
    pymidi run --mode blocking
    
  7. (Optional) Background Service: You can also install as a background service: see Service.

⚙️ Configuration

All settings live in a single YAML file:

~/.config/pymidi-controller/config.yaml

This file will contain potentially sensitive data like your Hue API key or your IP address, so it will be flagged as senstive and set so only your user can read it.

Example config.yaml

hue:
  bridge_ip: 192.168.1.42      # your Hue Bridge address
  api_key: YOUR_HUE_API_KEY    # obtained via `pymidi hue discover`

elgato:
  host: 192.168.1.43           # your Elgato Ring Light address

midi:
  devices:
    - "Streamer X"
    - "nanoPAD"

  # Map MIDI event keys → pymidi commands
  bindings:
    control_change:0:12:127:
      - hue
      - toggle-group
      - "Living Room"
    control_change:0:14:127:
      - elgato
      - toggle

  # Optional: define color cycles per group
  color_cycles:
    Living Room:
      - red
      - blue
      - green

🎛️ Commands

Use pymidi <group> --help for details on each context.

Global

Command Description
pymidi init Create default config file and function dir
pymidi run [--mode interactive | blocking] Start the MIDI listener (--mode blocking)

Service

Command Description
pymidi service install --user Install & start as a user service
pymidi service install --system Install & start system-wide service
pymidi service uninstall --user Stop & remove user service
pymidi service uninstall --system Stop & remove system service
pymidi service stop Stop the running service
pymidi service enable Enable service (user scope)
pymidi service log Tail service logs

Hue Commands

Command Description
pymidi hue discover Find bridge & generate API key
pymidi hue list-groups List all groups and on/off states
pymidi hue list-lights List all lights and their state/effect
pymidi hue list-schedules List all schedules
pymidi hue toggle-group <group> Toggle a group on/off
pymidi hue set-color <group> <color> [--sat N] [--bri N] Set group color
pymidi hue toggle-schedule <name> Enable/disable a schedule
pymidi hue loop [--effect colorloop | none] Toggle colorloop effect
pymidi hue cycle-color <group> Cycle group color through color_cycles

Elgato Commands

Command Description
pymidi elgato discover Discover Ring Light via mDNS
pymidi elgato toggle Toggle Ring Light on/off
pymidi elgato info Show current Ring Light status

MIDI Commands

Command Description
pymidi midi listen Print incoming MIDI event keys for mapping

Custom Function Commands

Command Description
pymidi function list List all available custom functions
pymidi function run <name> [args...] Run a custom function by name with optional arguments

🎹 MIDI Binding Guide

  1. Run:
    pymidi midi listen
    
  2. Press a control (button/knob) to see its event key, e.g. control_change:0:12:127.
  3. Open ~/.config/pymidi-controller/config.yaml and under midi.bindings, add:
    bindings:
      control_change:0:12:127:
        - hue
        - toggle-group
        - "Living Room"
    
    Each value under the event key should be one part in order of the Commands
  4. Save and test:
    pymidi run --mode interactive
    

📜 Custom User Functions

You can define your own Python functions to run on MIDI events. These live in:

~/.config/pymidi-controller/functions/

This directory is created by pymidi init and permissioned as 0700 (only accessible to your user).

Supported Formats

Option 1: Single .py file

Structure:

functions/
└── my_function.py

Content:

Note, the function must have a main() function, and this will be the entry point.

def main(*args):
    print("Hello from my_function", args)

Option 2: Package folder

You can also use a subfolder with either an __init__.py or a main.py: These must have a main() function.

Structure A:

functions/
└── my_package/
    └── __init__.py

Structure B:

functions/
└── my_package/
    └── main.py

Content:

def main(*args):
    print("Hello from package function", args)

Then bind it in your config:

bindings:
  control_change:0:10:127:
    - custom
    - my_function
    - optional_arg1
    - optional_arg2

⚙️ Service (Optional)

To run automatically at login:

pymidi service install --user

Logs:

pymidi service log

📜 License

MIT © Alex Sandilands

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymidi_controller-0.2.0.tar.gz (19.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymidi_controller-0.2.0-py3-none-any.whl (21.2 kB view details)

Uploaded Python 3

File details

Details for the file pymidi_controller-0.2.0.tar.gz.

File metadata

  • Download URL: pymidi_controller-0.2.0.tar.gz
  • Upload date:
  • Size: 19.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for pymidi_controller-0.2.0.tar.gz
Algorithm Hash digest
SHA256 3e3a4e52a57e01d2a1dcd8fdea372a35d59e8b78e28d3f6b31975ef7f03aaa6e
MD5 df2bbb44cfa355e29b346a7db5408757
BLAKE2b-256 d6346b54441cd1b5ee10239b23940325da3994a4a4ce5b418c3bb1cccc0343f3

See more details on using hashes here.

File details

Details for the file pymidi_controller-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pymidi_controller-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3adc8e12567ebfea9d0f900fa872c1cb4b56b6c2e26a5b13c9c9f13521713bb4
MD5 3242a302b3441bdcf07a88f67740830c
BLAKE2b-256 74c74714ecba040736cb8d28a8c14eb1d049f66755488bdc7e795b30bfbcab05

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page