From 38bc9a2c137a0ff0224fada6dbcc52fcd784f2ab Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Sat, 21 Mar 2026 19:43:52 -0700 Subject: [PATCH] feat(examples): Add default visualization script Add script that renders the standard Mainline visualization using the graph-based DSL. This demonstrates the default behavior with: - Headlines source data - Scroll camera mode - Terminal display - Classic effects: noise, fade, glitch, firehose Files added: - examples/default_visualization.py - Main script - examples/default_visualization.toml - TOML configuration - examples/README.md - Documentation for all examples Usage: python examples/default_visualization.py --- examples/README.md | 87 +++++++++++++++++++++++++++++ examples/default_visualization.py | 86 ++++++++++++++++++++++++++++ examples/default_visualization.toml | 39 +++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 examples/README.md create mode 100644 examples/default_visualization.py create mode 100644 examples/default_visualization.toml diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..db4acbc --- /dev/null +++ b/examples/README.md @@ -0,0 +1,87 @@ +# Examples + +This directory contains example scripts demonstrating how to use Mainline's features. + +## Default Visualization + +**`default_visualization.py`** - Renders the standard Mainline visualization using the graph-based DSL. + +```bash +python examples/default_visualization.py +``` + +This script demonstrates: +- Graph-based pipeline configuration using TOML +- Default Mainline behavior: headlines source, scroll camera, terminal display +- Classic effects: noise, fade, glitch, firehose +- One-shot rendering (prints to stdout) + +### Configuration + +The visualization is defined in `default_visualization.toml`: + +```toml +[nodes.source] +type = "source" +source = "headlines" + +[nodes.camera] +type = "camera" +mode = "scroll" +speed = 1.0 + +[nodes.noise] +type = "effect" +effect = "noise" +intensity = 0.3 + +[nodes.fade] +type = "effect" +effect = "fade" +intensity = 0.5 + +[nodes.display] +type = "display" +backend = "terminal" + +[connections] +list = ["source -> camera -> noise -> fade -> display"] +``` + +## Graph DSL Demonstration + +**`graph_dsl_demo.py`** - Demonstrates the graph-based DSL in multiple ways: + +```bash +python examples/graph_dsl_demo.py +``` + +Shows: +- Imperative Python API for building graphs +- Dictionary-based API +- Graph validation (cycles, disconnected nodes) +- Different node types and configurations + +## Integration Test + +**`test_graph_integration.py`** - Tests the graph system with actual pipeline execution: + +```bash +python examples/test_graph_integration.py +``` + +Verifies: +- Graph loading from TOML +- Pipeline execution +- Output rendering +- Comparison with preset-based pipelines + +## Other Demos + +- **`demo-lfo-effects.py`** - LFO modulation of effect intensities (Pygame display) +- **`demo_oscilloscope.py`** - Oscilloscope visualization +- **`demo_image_oscilloscope.py`** - Image-based oscilloscope + +## Graph DSL Reference + +See `docs/graph-dsl.md` for complete documentation on the graph-based DSL syntax. diff --git a/examples/default_visualization.py b/examples/default_visualization.py new file mode 100644 index 0000000..304ce3f --- /dev/null +++ b/examples/default_visualization.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +""" +Default Mainline Visualization + +Renders the standard Mainline visualization using the graph-based DSL. +This demonstrates the default behavior: headlines source, scroll camera, +terminal display, with classic effects (noise, fade, glitch, firehose). + +Usage: + python examples/default_visualization.py + +The visualization will be rendered once and printed to stdout. +""" + +import sys +from pathlib import Path + +# Add the project root to Python path +sys.path.insert(0, str(Path(__file__).parent.parent)) + +from engine.effects.plugins import discover_plugins +from engine.pipeline.graph_toml import load_pipeline_from_toml +from engine.pipeline.params import PipelineParams + + +def main(): + """Render the default Mainline visualization.""" + print("Loading default Mainline visualization...") + print("=" * 70) + + # Discover effect plugins + discover_plugins() + + # Path to the TOML configuration + toml_path = Path(__file__).parent / "default_visualization.toml" + + if not toml_path.exists(): + print(f"Error: Configuration file not found: {toml_path}", file=sys.stderr) + sys.exit(1) + + # Load pipeline from TOML configuration + try: + pipeline = load_pipeline_from_toml( + toml_path, viewport_width=80, viewport_height=24 + ) + print(f"✓ Pipeline loaded from {toml_path.name}") + print(f" Stages: {list(pipeline._stages.keys())}") + except Exception as e: + print(f"Error loading pipeline: {e}", file=sys.stderr) + sys.exit(1) + + # Initialize the pipeline + if not pipeline.initialize(): + print("Error: Failed to initialize pipeline", file=sys.stderr) + sys.exit(1) + print("✓ Pipeline initialized") + + # Set up execution context + ctx = pipeline.context + ctx.terminal_width = 80 + ctx.terminal_height = 24 + + # Create params for the execution + params = PipelineParams(viewport_width=80, viewport_height=24) + ctx.params = params + + # Execute the pipeline (empty items list - source will provide content) + print("Executing pipeline...") + result = pipeline.execute([]) + + # Render output + if result.success: + print("=" * 70) + print("Visualization Output:") + print("=" * 70) + for i, line in enumerate(result.data): + print(line) + print("=" * 70) + print(f"✓ Successfully rendered {len(result.data)} lines") + else: + print(f"Error: Pipeline execution failed: {result.error}", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/examples/default_visualization.toml b/examples/default_visualization.toml new file mode 100644 index 0000000..4d79d36 --- /dev/null +++ b/examples/default_visualization.toml @@ -0,0 +1,39 @@ +# Default Mainline Visualization +# This configuration renders the standard Mainline visualization using the +# graph-based DSL. It matches the upstream-default preset behavior. + +[nodes.source] +type = "source" +source = "headlines" + +[nodes.camera] +type = "camera" +mode = "scroll" +speed = 1.0 + +[nodes.noise] +type = "effect" +effect = "noise" +intensity = 0.3 + +[nodes.fade] +type = "effect" +effect = "fade" +intensity = 0.5 + +[nodes.glitch] +type = "effect" +effect = "glitch" +intensity = 0.2 + +[nodes.firehose] +type = "effect" +effect = "firehose" +intensity = 0.4 + +[nodes.display] +type = "display" +backend = "terminal" + +[connections] +list = ["source -> camera -> noise -> fade -> glitch -> firehose -> display"]