A library for offline generation of Max/MSP patcher (.maxpat) files.
Project description
py2max
A pure Python library for offline generation of Max/MSP patcher files (.maxpat, .maxhelp, .rbnopat).
If you are looking for Python 3 externals for Max/MSP, check out the py-js project.
Installation
pip install py2max
# With interactive server support
pip install py2max[server]
For development:
git clone https://github.com/shakfu/py2max.git
cd py2max
uv sync
source .venv/bin/activate
Quick Start
from py2max import Patcher
p = Patcher('my-synth.maxpat')
osc = p.add('cycle~ 440')
gain = p.add('gain~')
dac = p.add('ezdac~')
p.link(osc, gain)
p.link(gain, dac)
p.save()
That's it! Open my-synth.maxpat in Max to see your patch.
Features
Core Capabilities
- Offline Patch Generation - Create Max patches programmatically without Max running
- Round-trip Conversion - Load, modify, and save existing
.maxpatfiles - Universal Object Support - Works with any Max/MSP/Jitter object
- 99% Test Coverage - 418+ tests ensure reliability
Interactive Server (New in 0.2.x)
Real-time browser-based patch editing with bidirectional sync:
py2max serve my-patch.maxpat
# Opens browser at http://localhost:8000
Features:
- Drag objects, draw connections visually
- Three layout engines: WebCola, ELK, and Dagre
- Auto-save with debouncing
- Navigate into subpatchers
- REPL mode for Python interaction
SVG Preview
Generate high-quality SVG previews without Max:
py2max preview my-patch.maxpat --open
p = Patcher('synth.maxpat')
# ... add objects ...
p.to_svg('synth.svg', title="My Synth", show_ports=True)
Layout Managers
Five built-in layout strategies:
| Layout | Description |
|---|---|
grid |
Connection-aware clustering with configurable flow |
flow |
Signal flow-based hierarchical positioning |
columnar |
Controls -> Generators -> Processors -> Outputs |
matrix |
Signal chains in columns, categories in rows |
horizontal/vertical |
Simple grid layouts |
p = Patcher('patch.maxpat', layout='flow', flow_direction='vertical')
# Add objects and connections...
p.optimize_layout() # Arrange based on signal flow
p.save()
MaxRef Integration
Access documentation for 1157 Max objects:
p = Patcher('demo.maxpat')
cycle = p.add('cycle~ 440')
print(cycle.help()) # Full documentation
print(f"Inlets: {cycle.get_inlet_count()}")
print(f"Outlets: {cycle.get_outlet_count()}")
Connection Validation
Optional validation catches wiring errors:
p = Patcher('patch.maxpat', validate_connections=True)
osc = p.add('cycle~ 440')
gain = p.add('gain~')
p.link(osc, gain) # Valid
p.link(osc, gain, outlet=5) # Raises InvalidConnectionError
Semantic IDs
Human-readable object IDs for easier debugging:
p = Patcher('patch.maxpat', semantic_ids=True)
osc1 = p.add('cycle~ 440') # ID: 'cycle_1'
osc2 = p.add('cycle~ 220') # ID: 'cycle_2'
gain = p.add('gain~') # ID: 'gain_1'
# Find by semantic ID
osc = p.find_by_id('cycle_1')
SQLite Database
Query Max object metadata efficiently:
from py2max import MaxRefDB
db = MaxRefDB() # Auto-cached on first use
print(len(db)) # 1157 objects
if 'cycle~' in db:
info = db['cycle~']
print(info['digest'])
# Search and filter
results = db.search('filter')
msp_objects = db.by_category('MSP')
Usage Examples
Basic Patch Creation
from py2max import Patcher
p = Patcher('my-patch.maxpat')
osc = p.add('cycle~ 440')
gain = p.add('gain~')
dac = p.add('ezdac~')
p.link(osc, gain)
p.link(gain, dac)
p.link(gain, dac, inlet=1) # Stereo
p.save()
Loading and Modifying Patches
p = Patcher.from_file('existing.maxpat')
# Find and modify objects
for box in p.find_by_text('cycle~'):
print(f"Found oscillator: {box.id}")
p.save_as('modified.maxpat')
Subpatchers
p = Patcher('main.maxpat')
sbox = p.add_subpatcher('p mysub')
sp = sbox.subpatcher
# Build the subpatcher
inlet = sp.add('inlet')
gain = sp.add('gain~')
outlet = sp.add('outlet')
sp.link(inlet, gain)
sp.link(gain, outlet)
# Connect in main patcher
osc = p.add('cycle~ 440')
dac = p.add('ezdac~')
p.link(osc, sbox)
p.link(sbox, dac)
p.save()
Object Search
p = Patcher.from_file('complex-patch.maxpat')
# Find by ID
obj = p.find_by_id('obj-5')
# Find by text content
oscillators = p.find_by_text('cycle~')
# Find by object type
messages = p.find_by_type('message')
Command Line Interface
Patch Management
# Create new patch from template
py2max new demo.maxpat --template stereo
# Show patch info
py2max info demo.maxpat
# Generate SVG preview
py2max preview demo.maxpat --open
# Optimize layout
py2max optimize demo.maxpat --layout flow
# Validate connections
py2max validate demo.maxpat
Interactive Server
# Start server with browser editing
py2max serve my-patch.maxpat
# With REPL in same terminal
py2max serve my-patch.maxpat --repl
MaxRef Database
# Show cache status
py2max db cache location
# Create category-specific database
py2max db create msp.db --category msp
# Search objects
py2max db search maxref.db "oscillator" -v
# Query specific object
py2max db query maxref.db cycle~ --json
Converters
# Convert .maxpat to Python code
py2max convert maxpat-to-python patch.maxpat output.py
# Lookup object documentation
py2max maxref cycle~ --json
Use Cases
- Scripted patch generation - Automate repetitive patch creation
- Batch processing - Modify multiple
.maxpatfiles programmatically - Parametric patches - Generate variations from configuration files
- Test generation - Create
.maxhelpfiles during external development - Container population - Prepopulate
coll,dict,tableobjects with data - Generative patching - Algorithmic patch creation
- CI/CD integration - SVG previews for documentation and version control
Testing
make test # Run all tests
make typecheck # Type checking with mypy
make lint # Linting with ruff
make docs # Build documentation
Design Notes
The .maxpat JSON format maps directly to three Python classes:
Patcher- The patch container with boxes and patchlinesBox- Individual Max objectsPatchline- Connections between boxes
All classes are extendable via **kwargs, allowing any Max object configuration. The add_textbox() method handles most objects, with specialized methods (add_subpatcher(), add_coll(), etc.) for objects requiring extra configuration.
Caveats
- Max doesn't refresh from file when open - close and reopen to see changes, or use
py2max servefor live editing - For tilde variants, use the
_tildesuffix:p.add_gen()vsp.add_gen_tilde() - API docs in progress - see
CLAUDE.mdfor comprehensive usage
Examples
See the examples/ directory for demonstrations:
auto_layout_demo.py- Complex synthesizer with layout optimizationnested_patcher_demo.py- Subpatcher navigationcolumnar_layout_demo.py- Functional column organizationmatrix_layout_demo.py- Signal chain matrix layout
External usage:
- faust2rnbo - Generate Max patchers for RNBO
Contributing
We welcome contributions! See CONTRIBUTING.md for guidelines.
git clone https://github.com/shakfu/py2max.git
cd py2max
uv sync
source .venv/bin/activate
make test # Verify setup
License
MIT License. See LICENSE for details.
Credits
- HOLA algorithm: Kieffer, Dwyer, Marriott, Wybrow (IEEE 2016)
- NetworkX: Hagberg, Schult, Swart (SciPy 2008)
- Graph drawing techniques: Gansner, Koutsofios, North, Vo (IEEE 1993)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file py2max-0.2.1.tar.gz.
File metadata
- Download URL: py2max-0.2.1.tar.gz
- Upload date:
- Size: 987.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8a4ce84acfdd79508d73fd319ad3a347cca2fd5fb7bbaccc3bb8caa877642b8
|
|
| MD5 |
e7adf50b4a9021548412e28dc5c1e7bc
|
|
| BLAKE2b-256 |
0b4575d4fa0afc395aaf46b827bcd1467f9807f7e886f9c095216ce3e57b4eab
|
File details
Details for the file py2max-0.2.1-py3-none-any.whl.
File metadata
- Download URL: py2max-0.2.1-py3-none-any.whl
- Upload date:
- Size: 871.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5c6d654d84c480faca82d5408b56452757d4b2ee6c282752ddbf4cc10972eca
|
|
| MD5 |
a1ff57c41c2f7028c93e02bf6735e989
|
|
| BLAKE2b-256 |
d321c7bd17d9107b17a424030b7479d50947c94d573c973b4e66a9ee049ce5fe
|