Skip to main content

A library for offline generation of Max/MSP patcher (.maxpat) files.

Project description

py2max

Python 3.9+ License: MIT

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

For the browser-based live editor and remote REPL, install the companion py2max-server package:

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 .maxpat files
  • Universal Object Support - Works with any Max/MSP/Jitter object
  • 99% Test Coverage - 418+ tests ensure reliability

Interactive Server (separate package)

Real-time browser-based patch editing with bidirectional sync lives in the companion py2max-server package, so the core library stays small and offline:

pip install py2max-server
py2max-server 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

Provided by the separate py2max-server package (pip install py2max-server):

# Start server with browser editing
py2max-server serve my-patch.maxpat

# With REPL in same terminal
py2max-server 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 .maxpat files programmatically
  • Parametric patches - Generate variations from configuration files
  • Test generation - Create .maxhelp files during external development
  • Container population - Prepopulate coll, dict, table objects 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 patchlines
  • Box - Individual Max objects
  • Patchline - 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-server serve (from the separate py2max-server package) for live editing
  • For tilde variants, use the _tilde suffix: p.add_gen() vs p.add_gen_tilde()
  • API docs in progress - see CLAUDE.md for comprehensive usage

Examples

The tests/examples/ directory contains working, tested examples organized by topic (see its README):

  • quickstart/basic_patch.py - Simple oscillator patch
  • tutorial/signal_processing_chain.py - Complex audio processing chain
  • tutorial/generative_music.py - Generative music system with patterns
  • layout/grid_layout_examples.py - Grid layout with clustering
  • advanced/data_containers.py - Tables, collections, and dictionaries
  • api/patcher_api_examples.py - Patcher API reference examples

External usage:

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


Download files

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

Source Distribution

py2max-0.3.0.tar.gz (1.3 MB view details)

Uploaded Source

Built Distribution

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

py2max-0.3.0-py3-none-any.whl (1.1 MB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: py2max-0.3.0.tar.gz
  • Upload date:
  • Size: 1.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for py2max-0.3.0.tar.gz
Algorithm Hash digest
SHA256 dd255f859095dba8b376fd18027e8440b23d8ed43e60ad1c9c026a635b77a4fa
MD5 52ad426b8528ca6d24205808a70f5954
BLAKE2b-256 365329c1bc6f5f584efe6bf1944379e73fcef01a14df629443b3ddb8c6e81f9b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: py2max-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for py2max-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c32389b2ce613d093c51d6c48da028ce64280734232c19233346b7b37e55f877
MD5 02c8e49b02e8ad5e4bf25d3bb3a2ba61
BLAKE2b-256 68c82806e2e7fdf717c8a65ea31bf9ba4764fc481c8092f4cf514df3591e47e5

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