forked from genewildish/Mainline
- Add for quick startup using first N feeds - Add background thread for full fetch and caching - Update to use fast fetch - Update docs and skills
224 lines
6.7 KiB
Markdown
224 lines
6.7 KiB
Markdown
# Mainline Pipeline
|
|
|
|
## Architecture Overview
|
|
|
|
The Mainline pipeline uses a **Stage-based architecture** with **capability-based dependency resolution**. Stages declare capabilities (what they provide) and dependencies (what they need), and the Pipeline resolves dependencies using prefix matching.
|
|
|
|
```
|
|
Source Stage → Render Stage → Effect Stages → Display Stage
|
|
↓
|
|
Camera Stage (provides camera.state capability)
|
|
```
|
|
|
|
### Capability-Based Dependency Resolution
|
|
|
|
Stages declare capabilities and dependencies:
|
|
- **Capabilities**: What the stage provides (e.g., `source`, `render.output`, `display.output`, `camera.state`)
|
|
- **Dependencies**: What the stage needs (e.g., `source`, `render.output`, `camera.state`)
|
|
|
|
The Pipeline resolves dependencies using **prefix matching**:
|
|
- `"source"` matches `"source.headlines"`, `"source.poetry"`, etc.
|
|
- `"camera.state"` matches the camera state capability provided by `CameraClockStage`
|
|
- This allows flexible composition without hardcoding specific stage names
|
|
|
|
### Minimum Capabilities
|
|
|
|
The pipeline requires these minimum capabilities to function:
|
|
- `"source"` - Data source capability (provides raw items)
|
|
- `"render.output"` - Rendered content capability
|
|
- `"display.output"` - Display output capability
|
|
- `"camera.state"` - Camera state for viewport filtering
|
|
|
|
These are automatically injected if missing by the `ensure_minimum_capabilities()` method.
|
|
|
|
### Stage Registry
|
|
|
|
The `StageRegistry` discovers and registers stages automatically:
|
|
- Scans `engine/stages/` for stage implementations
|
|
- Registers stages by their declared capabilities
|
|
- Enables runtime stage discovery and composition
|
|
|
|
## Stage-Based Pipeline Flow
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
subgraph Stages["Stage Pipeline"]
|
|
subgraph SourceStage["Source Stage (provides: source.*)"]
|
|
Headlines[HeadlinesSource]
|
|
Poetry[PoetrySource]
|
|
Pipeline[PipelineSource]
|
|
end
|
|
|
|
subgraph RenderStage["Render Stage (provides: render.*)"]
|
|
Render[RenderStage]
|
|
Canvas[Canvas]
|
|
Camera[Camera]
|
|
end
|
|
|
|
subgraph EffectStages["Effect Stages (provides: effect.*)"]
|
|
Noise[NoiseEffect]
|
|
Fade[FadeEffect]
|
|
Glitch[GlitchEffect]
|
|
Firehose[FirehoseEffect]
|
|
Hud[HudEffect]
|
|
end
|
|
|
|
subgraph DisplayStage["Display Stage (provides: display.*)"]
|
|
Terminal[TerminalDisplay]
|
|
Pygame[PygameDisplay]
|
|
WebSocket[WebSocketDisplay]
|
|
Null[NullDisplay]
|
|
end
|
|
end
|
|
|
|
subgraph Capabilities["Capability Map"]
|
|
SourceCaps["source.headlines<br/>source.poetry<br/>source.pipeline"]
|
|
RenderCaps["render.output<br/>render.canvas"]
|
|
EffectCaps["effect.noise<br/>effect.fade<br/>effect.glitch"]
|
|
DisplayCaps["display.output<br/>display.terminal"]
|
|
end
|
|
|
|
SourceStage --> RenderStage
|
|
RenderStage --> EffectStages
|
|
EffectStages --> DisplayStage
|
|
|
|
SourceStage --> SourceCaps
|
|
RenderStage --> RenderCaps
|
|
EffectStages --> EffectCaps
|
|
DisplayStage --> DisplayCaps
|
|
|
|
style SourceStage fill:#f9f,stroke:#333
|
|
style RenderStage fill:#bbf,stroke:#333
|
|
style EffectStages fill:#fbf,stroke:#333
|
|
style DisplayStage fill:#bfb,stroke:#333
|
|
```
|
|
|
|
## Stage Adapters
|
|
|
|
Existing components are wrapped as Stages via adapters:
|
|
|
|
### Source Stage Adapter
|
|
- Wraps `HeadlinesDataSource`, `PoetryDataSource`, etc.
|
|
- Provides `source.*` capabilities
|
|
- Fetches data and outputs to pipeline buffer
|
|
|
|
### Render Stage Adapter
|
|
- Wraps `StreamController`, `Camera`, `render_ticker_zone`
|
|
- Provides `render.output` capability
|
|
- Processes content and renders to canvas
|
|
|
|
### Effect Stage Adapter
|
|
- Wraps `EffectChain` and individual effect plugins
|
|
- Provides `effect.*` capabilities
|
|
- Applies visual effects to rendered content
|
|
|
|
### Display Stage Adapter
|
|
- Wraps `TerminalDisplay`, `PygameDisplay`, etc.
|
|
- Provides `display.*` capabilities
|
|
- Outputs final buffer to display backend
|
|
|
|
## Pipeline Mutation API
|
|
|
|
The Pipeline supports dynamic mutation during runtime:
|
|
|
|
### Core Methods
|
|
- `add_stage(name, stage, initialize=True)` - Add a stage
|
|
- `remove_stage(name, cleanup=True)` - Remove a stage and rebuild execution order
|
|
- `replace_stage(name, new_stage, preserve_state=True)` - Replace a stage
|
|
- `swap_stages(name1, name2)` - Swap two stages
|
|
- `move_stage(name, after=None, before=None)` - Move a stage in execution order
|
|
- `enable_stage(name)` / `disable_stage(name)` - Enable/disable stages
|
|
|
|
### Safety Checks
|
|
- `can_hot_swap(name)` - Check if a stage can be safely hot-swapped
|
|
- `cleanup_stage(name)` - Clean up specific stage without removing it
|
|
|
|
### WebSocket Commands
|
|
The mutation API is accessible via WebSocket for remote control:
|
|
```json
|
|
{"action": "remove_stage", "stage": "stage_name"}
|
|
{"action": "swap_stages", "stage1": "name1", "stage2": "name2"}
|
|
{"action": "enable_stage", "stage": "stage_name"}
|
|
{"action": "cleanup_stage", "stage": "stage_name"}
|
|
```
|
|
|
|
## Camera Modes
|
|
|
|
The Camera supports the following modes:
|
|
|
|
- **FEED**: Single item view (static or rapid cycling)
|
|
- **SCROLL**: Smooth vertical scrolling (movie credits style)
|
|
- **HORIZONTAL**: Left/right movement
|
|
- **OMNI**: Combination of vertical and horizontal
|
|
- **FLOATING**: Sinusoidal/bobbing motion
|
|
- **BOUNCE**: DVD-style bouncing off edges
|
|
- **RADIAL**: Polar coordinate scanning (radar sweep)
|
|
|
|
Note: Camera state is provided by `CameraClockStage` (capability: `camera.state`) which updates independently of data flow. The `CameraStage` applies viewport transformations (capability: `camera`).
|
|
|
|
## Animation & Presets
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph Preset["Preset"]
|
|
PP[PipelineParams]
|
|
AC[AnimationController]
|
|
end
|
|
|
|
subgraph AnimationController["AnimationController"]
|
|
Clock[Clock]
|
|
Events[Events]
|
|
Triggers[Triggers]
|
|
end
|
|
|
|
subgraph Triggers["Trigger Types"]
|
|
TIME[TIME]
|
|
FRAME[FRAME]
|
|
CYCLE[CYCLE]
|
|
COND[CONDITION]
|
|
MANUAL[MANUAL]
|
|
end
|
|
|
|
PP --> AC
|
|
Clock --> AC
|
|
Events --> AC
|
|
Triggers --> Events
|
|
```
|
|
|
|
## Camera Modes State Diagram
|
|
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> Vertical
|
|
Vertical --> Horizontal: mode change
|
|
Horizontal --> Omni: mode change
|
|
Omni --> Floating: mode change
|
|
Floating --> Trace: mode change
|
|
Trace --> Vertical: mode change
|
|
|
|
state Vertical {
|
|
[*] --> ScrollUp
|
|
ScrollUp --> ScrollUp: +y each frame
|
|
}
|
|
|
|
state Horizontal {
|
|
[*] --> ScrollLeft
|
|
ScrollLeft --> ScrollLeft: +x each frame
|
|
}
|
|
|
|
state Omni {
|
|
[*] --> Diagonal
|
|
Diagonal --> Diagonal: +x, +y each frame
|
|
}
|
|
|
|
state Floating {
|
|
[*] --> Bobbing
|
|
Bobbing --> Bobbing: sin(time) for x,y
|
|
}
|
|
|
|
state Trace {
|
|
[*] --> FollowPath
|
|
FollowPath --> FollowPath: node by node
|
|
}
|
|
```
|