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

> Discover bouncy links in nallely-midi. Learn how these specialized parameter connections trigger reaction chains, cascading control changes through multiple destinations simultaneously.

- Repository: [dr-schlange/nallely-midi](https://github.com/dr-schlange/nallely-midi)
- Tags: deep-dive
- Published: 2026-02-28

---

**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.

## Understanding Bouncy Links and Reaction Chains

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.

## How Bouncy Links Work Under the Hood

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

### The Link Class and Bouncy Flag

In [`nallely/core/links.py`](https://github.com/dr-schlange/nallely-midi/blob/main/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.

### The bounce_link Method

Both hardware and virtual devices implement the `bounce_link` method to scan for related connections. In [`nallely/core/midi_device.py`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/core/midi_device.py) (lines 74-79) and [`nallely/core/virtual_device.py`](https://github.com/dr-schlange/nallely-midi/blob/main/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`](https://github.com/dr-schlange/nallely-midi/blob/main/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 detection** → `Link.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 scan** → `bounce_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

### Creating a Bouncy Link via the API

```python
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`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/core/links.py) implements the bouncy logic:

```python
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:

```python
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:

```text
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`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/core/midi_device.py)) and **virtual devices** ([`nallely/core/virtual_device.py`](https://github.com/dr-schlange/nallely-midi/blob/main/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

### What is the difference between a standard link and a bouncy link?

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.

### Can bouncy links create infinite loops?

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.

### How do I disable the bouncy behavior on an existing link?

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.

### Do bouncy links work with both hardware MIDI devices and virtual software synths?

Yes. The `bounce_link` method is implemented in both `MidiDevice` ([`nallely/core/midi_device.py`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/core/midi_device.py)) and `VirtualDevice` ([`nallely/core/virtual_device.py`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/core/virtual_device.py)), ensuring consistent reaction chain behavior across hardware controllers and virtual instruments within the nallely-midi framework.