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.3.0.tar.gz (19.1 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.3.0-py3-none-any.whl (21.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pymidi_controller-0.3.0.tar.gz
  • Upload date:
  • Size: 19.1 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.3.0.tar.gz
Algorithm Hash digest
SHA256 60e0d87513d54846263b76815f56150ffd3fd5d48d1cb0b2684455ff58f91c8a
MD5 d8f5cd48878a585f1d067324d29bb7fb
BLAKE2b-256 8278295f1bec2ba4cd09a7aac93031de7c5cd56ca8bcce742b199bdb161ebf86

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymidi_controller-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f67833c8c9e03ebb769ec713b749095e50aad52d0ff503a70a5e3b655367d464
MD5 fcf5db2d1b81cc267677a78cd89b0635
BLAKE2b-256 57c56d10edc58d2dd308ab9ce7eb5c139088ab4bb5b1f5f33724f08598ce0339

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