What Are Bouncy Links and How Do They Trigger Reaction Chains in Nallely-MIDI

Bouncy links are specialized parameter connections in nallely-midi that automatically re-trigger every other link sharing the same source, creating reaction chains where a single control change cascades through multiple destinations simultaneously.

Bouncy links provide a powerful mechanism for building reactive MIDI device graphs in the dr-schlange/nallely-midi framework. By marking a parameter connection as bouncy, developers enable automatic propagation of changes across all related links without manual rebinding. This architecture simplifies complex modulation scenarios where one source parameter must drive multiple destinations in unison.

A bouncy link is a connection between two parameters (source → destination) that, when triggered, automatically invokes every other link that shares the same source path. This creates a reaction chain: a cascading update where a single change on the source parameter propagates through all linked destinations, allowing one control movement to affect many parts of a device graph simultaneously.

Unlike standard static bindings, bouncy links enable dynamic fan-out behavior without requiring explicit individual associations for every destination.

The implementation spans four core files in the nallely-midi codebase, each handling a specific aspect of the bouncy link lifecycle.

In nallely/core/links.py, the Link class stores the connection metadata and a boolean bouncy flag initialized in Link.__init__ (lines 48-56). When Link.trigger executes (lines 94-109), it first applies its own callback to update the destination parameter. If self.bouncy is True, it then invokes self.dest.device.bounce_link(self.dest, value, ctx) to initiate the reaction chain.

Both hardware and virtual devices implement the bounce_link method to scan for related connections. In nallely/core/midi_device.py (lines 74-79) and nallely/core/virtual_device.py (lines 58-63), the method accepts the source parameter, value, and context, then iterates through the device's links_registry to find all links sharing the same src_path. Each matching link receives a recursive trigger call, continuing the chain.

The Public API

The TrevorAPI class in nallely/trevor/trevor_api.py provides make_link_bouncy (lines 101-110), a public interface that toggles the bouncy flag on existing links. This allows developers to convert standard parameter associations into bouncy connections at runtime without directly manipulating Link objects.

Step-by-Step Execution Flow

When a bouncy link fires, the following sequence occurs:

  1. Source change detectionLink.trigger receives the new value and context.
  2. Local update → The link's callback updates its immediate destination parameter.
  3. Bounce invocation → Because self.bouncy is True, the link calls dest.device.bounce_link.
  4. Registry scanbounce_link looks up all links registered with the same source path.
  5. Chain propagation → Each matching link is re-triggered, potentially activating additional bouncy links and continuing the cascade.

Practical Implementation Examples

from nallely.trevor import TrevorAPI

api = TrevorAPI()

# Create a standard link between a synth parameter and a panel indicator

api.associate_parameters(
    from_parameter="Synth::filter::cutoff",
    to_parameter="Panel::led::filter_indicator"
)

# Convert the link to bouncy to enable reaction chains

api.make_link_bouncy(
    from_parameter="Synth::filter::cutoff",
    to_parameter="Panel::led::filter_indicator",
    bouncy=True
)

When the cutoff knob moves, the LED updates and any other links using Synth::filter::cutoff as their source automatically trigger.

Internal Trigger Flow

The Link.trigger method in nallely/core/links.py implements the bouncy logic:

def trigger(self, value, ctx):
    # Apply the link's own callback first

    self.callback(value, ctx)
    
    # If bouncy, ask the destination device to rebroadcast

    if self.bouncy:
        self.dest.device.bounce_link(self.dest, value, ctx)

The device's bounce_link method then handles the cascade:

def bounce_link(self, from_, value, ctx):
    src_path = from_.repr()
    for (src, _), link in list(self.links_registry.items()):
        if src == src_path:          # Same source as the original link?

            link.trigger(value, ctx) # Re-trigger to continue the chain

Multi-Parameter Reaction Chain Example

Consider three links sharing the modwheel source:

Link A: Synth::modwheel -> ModDepth (bouncy)
Link B: Synth::modwheel -> LFO::rate
Link C: Synth::modwheel -> Env::attack

When the modwheel changes:

  • Link A updates ModDepth and calls bounce_link because it is bouncy.
  • The device finds Link B and Link C sharing the same Synth::modwheel source.
  • Both links trigger simultaneously, updating the LFO rate and envelope attack.

All three parameters react to a single control movement, demonstrating the reaction chain pattern.

Summary

  • Bouncy links in nallely-midi are parameter connections marked with a bouncy=True flag that automatically propagate changes to all other links sharing the same source.
  • The reaction chain mechanism relies on Link.trigger checking the bouncy flag and calling bounce_link, which scans the device's link registry for matches.
  • Both MIDI devices (nallely/core/midi_device.py) and virtual devices (nallely/core/virtual_device.py) implement the bounce_link method to support hardware and software synths.
  • The TrevorAPI.make_link_bouncy method provides a clean public interface for enabling this behavior without direct Link manipulation.
  • This architecture enables complex, single-source-to-multi-destination modulation graphs with minimal configuration code.

Frequently Asked Questions

A standard link creates a one-to-one connection between a source and destination parameter. A bouncy link extends this by automatically triggering all other links that share the same source path after executing its own update, creating a one-to-many propagation pattern known as a reaction chain.

The nallely-midi implementation prevents infinite recursion because bounce_link only triggers links that share the exact same source path as the original triggering link. Since links are unidirectional (source → destination) and the bounce operation specifically targets co-source links rather than following destination-to-source cycles, the chain naturally terminates after all matching links fire once.

Call TrevorAPI.make_link_bouncy() with bouncy=False for the specific source-destination pair. This sets the Link.bouncy attribute to False, causing future triggers to execute only the local callback without invoking bounce_link or propagating to other connections.

Yes. The bounce_link method is implemented in both MidiDevice (nallely/core/midi_device.py) and VirtualDevice (nallely/core/virtual_device.py), ensuring consistent reaction chain behavior across hardware controllers and virtual instruments within the nallely-midi framework.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →