forked from genewildish/Mainline
feat(graph): Integrate graph system with pipeline runner
Add support for loading pipelines from TOML graph configs in the pipeline runner, maintaining full backward compatibility with presets. - Add graph_config parameter to run_pipeline_mode() function - Support both preset mode and graph mode with conditional logic - Graph mode: loads from TOML file, uses graph-defined stages - Preset mode: maintains existing behavior with manual stage building - Handle items/context appropriately for each mode (graph uses own data sources) - CLI display flag works in both modes Backward compatible: graph_config defaults to None, so existing calls to run_pipeline_mode(preset_name) continue to work unchanged.
This commit is contained in:
@@ -104,8 +104,13 @@ def _handle_pipeline_mutation(pipeline: Pipeline, command: dict) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def run_pipeline_mode(preset_name: str = "demo"):
|
def run_pipeline_mode(preset_name: str = "demo", graph_config: str | None = None):
|
||||||
"""Run using the new unified pipeline architecture."""
|
"""Run using the new unified pipeline architecture.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
preset_name: Name of the preset to use
|
||||||
|
graph_config: Path to a TOML graph configuration file (optional)
|
||||||
|
"""
|
||||||
import engine.effects.plugins as effects_plugins
|
import engine.effects.plugins as effects_plugins
|
||||||
from engine.effects import PerformanceMonitor, set_monitor
|
from engine.effects import PerformanceMonitor, set_monitor
|
||||||
|
|
||||||
@@ -117,6 +122,53 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
monitor = PerformanceMonitor()
|
monitor = PerformanceMonitor()
|
||||||
set_monitor(monitor)
|
set_monitor(monitor)
|
||||||
|
|
||||||
|
# Check if graph config is provided
|
||||||
|
using_graph_config = graph_config is not None
|
||||||
|
|
||||||
|
if using_graph_config:
|
||||||
|
from engine.pipeline.graph_toml import load_pipeline_from_toml
|
||||||
|
|
||||||
|
print(f" \033[38;5;245mLoading graph from: {graph_config}\033[0m")
|
||||||
|
|
||||||
|
# Determine viewport size
|
||||||
|
viewport_width = 80
|
||||||
|
viewport_height = 24
|
||||||
|
if "--viewport" in sys.argv:
|
||||||
|
idx = sys.argv.index("--viewport")
|
||||||
|
if idx + 1 < len(sys.argv):
|
||||||
|
vp = sys.argv[idx + 1]
|
||||||
|
try:
|
||||||
|
viewport_width, viewport_height = map(int, vp.split("x"))
|
||||||
|
except ValueError:
|
||||||
|
print("Error: Invalid viewport format. Use WxH (e.g., 40x15)")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Load pipeline from graph config
|
||||||
|
try:
|
||||||
|
pipeline = load_pipeline_from_toml(
|
||||||
|
graph_config,
|
||||||
|
viewport_width=viewport_width,
|
||||||
|
viewport_height=viewport_height,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f" \033[38;5;196mError loading graph config: {e}\033[0m")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Set params for display
|
||||||
|
from engine.pipeline.params import PipelineParams
|
||||||
|
|
||||||
|
params = PipelineParams(
|
||||||
|
viewport_width=viewport_width, viewport_height=viewport_height
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set display name from graph or CLI
|
||||||
|
display_name = "terminal" # Default for graph mode
|
||||||
|
if "--display" in sys.argv:
|
||||||
|
idx = sys.argv.index("--display")
|
||||||
|
if idx + 1 < len(sys.argv):
|
||||||
|
display_name = sys.argv[idx + 1]
|
||||||
|
else:
|
||||||
|
# Use preset-based pipeline
|
||||||
preset = get_preset(preset_name)
|
preset = get_preset(preset_name)
|
||||||
if not preset:
|
if not preset:
|
||||||
print(f" \033[38;5;196mUnknown preset: {preset_name}\033[0m")
|
print(f" \033[38;5;196mUnknown preset: {preset_name}\033[0m")
|
||||||
@@ -196,10 +248,12 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
|
|
||||||
print(f" \033[38;5;82mLoaded {len(items)} items\033[0m")
|
print(f" \033[38;5;82mLoaded {len(items)} items\033[0m")
|
||||||
|
|
||||||
# CLI --display flag takes priority over preset
|
# CLI --display flag takes priority
|
||||||
# Check if --display was explicitly provided
|
# Check if --display was explicitly provided
|
||||||
display_name = preset.display
|
|
||||||
display_explicitly_specified = "--display" in sys.argv
|
display_explicitly_specified = "--display" in sys.argv
|
||||||
|
if not using_graph_config:
|
||||||
|
# Preset mode: use preset display as default
|
||||||
|
display_name = preset.display
|
||||||
if display_explicitly_specified:
|
if display_explicitly_specified:
|
||||||
idx = sys.argv.index("--display")
|
idx = sys.argv.index("--display")
|
||||||
if idx + 1 < len(sys.argv):
|
if idx + 1 < len(sys.argv):
|
||||||
@@ -212,6 +266,10 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
print(
|
print(
|
||||||
" \033[38;5;245mTip: Use --display null for headless mode (useful for testing/capture)\033[0m"
|
" \033[38;5;245mTip: Use --display null for headless mode (useful for testing/capture)\033[0m"
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
# Graph mode: display_name already set above
|
||||||
|
if not display_explicitly_specified:
|
||||||
|
print(f" \033[38;5;245mUsing default display: {display_name}\033[0m")
|
||||||
|
|
||||||
display = DisplayRegistry.create(display_name)
|
display = DisplayRegistry.create(display_name)
|
||||||
if not display and not display_name.startswith("multi"):
|
if not display and not display_name.startswith("multi"):
|
||||||
@@ -245,6 +303,9 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
|
|
||||||
effect_registry = get_registry()
|
effect_registry = get_registry()
|
||||||
|
|
||||||
|
# Only build stages from preset if not using graph config
|
||||||
|
# (graph config already has all stages defined)
|
||||||
|
if not using_graph_config:
|
||||||
# Create source stage based on preset source type
|
# Create source stage based on preset source type
|
||||||
if preset.source == "pipeline-inspect":
|
if preset.source == "pipeline-inspect":
|
||||||
from engine.data_sources.pipeline_introspection import (
|
from engine.data_sources.pipeline_introspection import (
|
||||||
@@ -271,7 +332,9 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
from engine.pipeline.adapters import DataSourceStage
|
from engine.pipeline.adapters import DataSourceStage
|
||||||
|
|
||||||
list_source = ListDataSource(items, name=preset.source)
|
list_source = ListDataSource(items, name=preset.source)
|
||||||
pipeline.add_stage("source", DataSourceStage(list_source, name=preset.source))
|
pipeline.add_stage(
|
||||||
|
"source", DataSourceStage(list_source, name=preset.source)
|
||||||
|
)
|
||||||
|
|
||||||
# Add camera state update stage if specified in preset (must run before viewport filter)
|
# Add camera state update stage if specified in preset (must run before viewport filter)
|
||||||
camera = None
|
camera = None
|
||||||
@@ -307,6 +370,8 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
"camera_update", CameraClockStage(camera, name="camera-clock")
|
"camera_update", CameraClockStage(camera, name="camera-clock")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Only build stages from preset if not using graph config
|
||||||
|
if not using_graph_config:
|
||||||
# Add FontStage for headlines/poetry (default for demo)
|
# Add FontStage for headlines/poetry (default for demo)
|
||||||
if preset.source in ["headlines", "poetry"]:
|
if preset.source in ["headlines", "poetry"]:
|
||||||
from engine.pipeline.adapters import FontStage, ViewportFilterStage
|
from engine.pipeline.adapters import FontStage, ViewportFilterStage
|
||||||
@@ -318,7 +383,9 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
pipeline.add_stage("font", FontStage(name="font"))
|
pipeline.add_stage("font", FontStage(name="font"))
|
||||||
else:
|
else:
|
||||||
# Fallback to simple conversion for other sources
|
# Fallback to simple conversion for other sources
|
||||||
pipeline.add_stage("render", SourceItemsToBufferStage(name="items-to-buffer"))
|
pipeline.add_stage(
|
||||||
|
"render", SourceItemsToBufferStage(name="items-to-buffer")
|
||||||
|
)
|
||||||
|
|
||||||
# Add camera stage if specified in preset (after font/render stage)
|
# Add camera stage if specified in preset (after font/render stage)
|
||||||
if camera:
|
if camera:
|
||||||
@@ -328,7 +395,8 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
effect = effect_registry.get(effect_name)
|
effect = effect_registry.get(effect_name)
|
||||||
if effect:
|
if effect:
|
||||||
pipeline.add_stage(
|
pipeline.add_stage(
|
||||||
f"effect_{effect_name}", create_stage_from_effect(effect, effect_name)
|
f"effect_{effect_name}",
|
||||||
|
create_stage_from_effect(effect, effect_name),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add message overlay stage if enabled
|
# Add message overlay stage if enabled
|
||||||
@@ -831,7 +899,13 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
ctx = pipeline.context
|
ctx = pipeline.context
|
||||||
ctx.params = params
|
ctx.params = params
|
||||||
ctx.set("display", display)
|
ctx.set("display", display)
|
||||||
|
# For graph mode, items might not be defined - use empty list if needed
|
||||||
|
if not using_graph_config:
|
||||||
ctx.set("items", items)
|
ctx.set("items", items)
|
||||||
|
else:
|
||||||
|
# Graph-based pipelines typically use their own data sources
|
||||||
|
# But we can set an empty list for compatibility
|
||||||
|
ctx.set("items", [])
|
||||||
ctx.set("pipeline", pipeline)
|
ctx.set("pipeline", pipeline)
|
||||||
ctx.set("pipeline_order", pipeline.execution_order)
|
ctx.set("pipeline_order", pipeline.execution_order)
|
||||||
ctx.set("camera_y", 0)
|
ctx.set("camera_y", 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user