forked from genewildish/Mainline
feat(pipeline): add unified pipeline architecture with Stage abstraction
- Add engine/pipeline/ module with Stage ABC, PipelineContext, PipelineParams - Stage provides unified interface for sources, effects, displays, cameras - Pipeline class handles DAG-based execution with dependency resolution - PipelinePreset for pre-configured pipelines (demo, poetry, pipeline, etc.) - Add PipelineParams as params layer for animation-driven config - Add StageRegistry for unified stage registration - Add sources_v2.py with DataSource.is_dynamic property - Add animation.py with Preset and AnimationController - Skip ntfy integration tests by default (require -m integration) - Skip e2e tests by default (require -m e2e) - Update pipeline.py with comprehensive introspection methods
This commit is contained in:
146
engine/app.py
146
engine/app.py
@@ -572,7 +572,7 @@ def run_pipeline_demo():
|
||||
get_registry,
|
||||
set_monitor,
|
||||
)
|
||||
from engine.pipeline_viz import generate_network_pipeline
|
||||
from engine.pipeline_viz import generate_large_network_viewport
|
||||
|
||||
print(" \033[1;38;5;46mMAINLINE PIPELINE DEMO\033[0m")
|
||||
print(" \033[38;5;245mInitializing...\033[0m")
|
||||
@@ -667,7 +667,7 @@ def run_pipeline_demo():
|
||||
|
||||
camera.update(config.FRAME_DT)
|
||||
|
||||
buf = generate_network_pipeline(w, h, frame_number)
|
||||
buf = generate_large_network_viewport(w, h, frame_number)
|
||||
|
||||
ctx = EffectContext(
|
||||
terminal_width=w,
|
||||
@@ -699,6 +699,144 @@ def run_pipeline_demo():
|
||||
print("\n \033[38;5;245mPipeline demo ended\033[0m")
|
||||
|
||||
|
||||
def run_preset_mode(preset_name: str):
|
||||
"""Run mode using animation presets."""
|
||||
from engine import config
|
||||
from engine.animation import (
|
||||
create_demo_preset,
|
||||
create_pipeline_preset,
|
||||
)
|
||||
from engine.camera import Camera
|
||||
from engine.display import DisplayRegistry
|
||||
from engine.effects import (
|
||||
EffectContext,
|
||||
PerformanceMonitor,
|
||||
get_effect_chain,
|
||||
get_registry,
|
||||
set_monitor,
|
||||
)
|
||||
from engine.sources_v2 import (
|
||||
PipelineDataSource,
|
||||
get_source_registry,
|
||||
init_default_sources,
|
||||
)
|
||||
|
||||
w, h = 80, 24
|
||||
|
||||
if preset_name == "demo":
|
||||
preset = create_demo_preset()
|
||||
init_default_sources()
|
||||
source = get_source_registry().default()
|
||||
elif preset_name == "pipeline":
|
||||
preset = create_pipeline_preset()
|
||||
source = PipelineDataSource(w, h)
|
||||
else:
|
||||
print(f" \033[38;5;196mUnknown preset: {preset_name}\033[0m")
|
||||
print(" Available: demo, pipeline")
|
||||
sys.exit(1)
|
||||
|
||||
print(f" \033[1;38;5;46mMAINLINE PRESET: {preset.name}\033[0m")
|
||||
print(f" \033[38;5;245m{preset.description}\033[0m")
|
||||
print(" \033[38;5;245mInitializing...\033[0m")
|
||||
|
||||
import effects_plugins
|
||||
|
||||
effects_plugins.discover_plugins()
|
||||
|
||||
registry = get_registry()
|
||||
chain = get_effect_chain()
|
||||
chain.set_order(["noise", "fade", "glitch", "firehose", "hud"])
|
||||
|
||||
monitor = PerformanceMonitor()
|
||||
set_monitor(monitor)
|
||||
chain._monitor = monitor
|
||||
|
||||
display = DisplayRegistry.create(preset.initial_params.display_backend)
|
||||
if not display:
|
||||
print(
|
||||
f" \033[38;5;196mFailed to create {preset.initial_params.display_backend} display\033[0m"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
display.init(w, h)
|
||||
display.clear()
|
||||
|
||||
camera = Camera.vertical()
|
||||
|
||||
print(" \033[38;5;82mStarting preset animation...\033[0m")
|
||||
print(" \033[38;5;245mPress Ctrl+C to exit\033[0m\n")
|
||||
|
||||
controller = preset.create_controller()
|
||||
frame_number = 0
|
||||
|
||||
try:
|
||||
while True:
|
||||
params = controller.update()
|
||||
|
||||
effect_name = params.get("current_effect", "none")
|
||||
intensity = params.get("effect_intensity", 0.0)
|
||||
camera_mode = params.get("camera_mode", "vertical")
|
||||
|
||||
if camera_mode == "vertical":
|
||||
camera = Camera.vertical(speed=params.get("camera_speed", 1.0))
|
||||
elif camera_mode == "horizontal":
|
||||
camera = Camera.horizontal(speed=params.get("camera_speed", 1.0))
|
||||
elif camera_mode == "omni":
|
||||
camera = Camera.omni(speed=params.get("camera_speed", 1.0))
|
||||
elif camera_mode == "floating":
|
||||
camera = Camera.floating(speed=params.get("camera_speed", 1.0))
|
||||
|
||||
camera.update(config.FRAME_DT)
|
||||
|
||||
for eff in registry.list_all().values():
|
||||
if eff.name == effect_name:
|
||||
eff.config.enabled = True
|
||||
eff.config.intensity = intensity
|
||||
elif eff.name not in ("hud",):
|
||||
eff.config.enabled = False
|
||||
|
||||
hud_effect = registry.get("hud")
|
||||
if hud_effect:
|
||||
hud_effect.config.params["display_effect"] = (
|
||||
f"{effect_name} / {camera_mode}"
|
||||
)
|
||||
hud_effect.config.params["display_intensity"] = intensity
|
||||
|
||||
source.viewport_width = w
|
||||
source.viewport_height = h
|
||||
items = source.get_items()
|
||||
buffer = items[0].content.split("\n") if items else [""] * h
|
||||
|
||||
ctx = EffectContext(
|
||||
terminal_width=w,
|
||||
terminal_height=h,
|
||||
scroll_cam=camera.y,
|
||||
ticker_height=h,
|
||||
camera_x=camera.x,
|
||||
mic_excess=0.0,
|
||||
grad_offset=0.0,
|
||||
frame_number=frame_number,
|
||||
has_message=False,
|
||||
items=[],
|
||||
)
|
||||
|
||||
result = chain.process(buffer, ctx)
|
||||
display.show(result)
|
||||
|
||||
new_w, new_h = display.get_dimensions()
|
||||
if new_w != w or new_h != h:
|
||||
w, h = new_w, new_h
|
||||
|
||||
frame_number += 1
|
||||
time.sleep(1 / 60)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
display.cleanup()
|
||||
print("\n \033[38;5;245mPreset ended\033[0m")
|
||||
|
||||
|
||||
def main():
|
||||
from engine import config
|
||||
from engine.pipeline import generate_pipeline_diagram
|
||||
@@ -711,6 +849,10 @@ def main():
|
||||
run_pipeline_demo()
|
||||
return
|
||||
|
||||
if config.PRESET:
|
||||
run_preset_mode(config.PRESET)
|
||||
return
|
||||
|
||||
if config.DEMO:
|
||||
run_demo_mode()
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user