64 lines
1.9 KiB
Python
64 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Dict, Optional
|
|
|
|
from flask import url_for
|
|
|
|
from models import Display, EventDisplayMap, Video, db
|
|
from sync import ActiveEventState, server_time_ms, set_trigger_event
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _build_assignments(event_id: int) -> Dict[str, str]:
|
|
maps = (
|
|
db.session.query(EventDisplayMap)
|
|
.filter_by(event_id=event_id)
|
|
.join(Display, EventDisplayMap.display_id == Display.id)
|
|
.join(Video, EventDisplayMap.video_id == Video.id)
|
|
.all()
|
|
)
|
|
assignments: Dict[str, str] = {}
|
|
for m in maps:
|
|
assignments[m.display.public_id] = url_for("main.media", filename=m.video.filename)
|
|
return assignments
|
|
|
|
|
|
def broadcast_trigger_state(state: ActiveEventState) -> None:
|
|
# Lazy import to avoid circular import (sockets -> event_manager -> sockets)
|
|
from sockets import socketio
|
|
|
|
for public_id, video_url in state.assignments.items():
|
|
socketio.emit(
|
|
"event_start",
|
|
{
|
|
"event_id": state.event_id,
|
|
"event_name": state.name,
|
|
"video_url": video_url,
|
|
"start_time_ms": state.start_time_ms,
|
|
"server_time_ms": server_time_ms(),
|
|
},
|
|
room=f"display:{public_id}",
|
|
)
|
|
|
|
|
|
def activate_trigger_event(event_id: int, start_ms: float, end_ms: float, name: str) -> Optional[ActiveEventState]:
|
|
"""Activate a triggered event, store it in-memory, and broadcast it to displays."""
|
|
assignments = _build_assignments(event_id)
|
|
if not assignments:
|
|
return None
|
|
|
|
state = ActiveEventState(
|
|
event_id=event_id,
|
|
name=name,
|
|
start_time_ms=start_ms,
|
|
end_time_ms=end_ms,
|
|
assignments=assignments,
|
|
)
|
|
set_trigger_event(state)
|
|
broadcast_trigger_state(state)
|
|
logger.info("Activated trigger event %s (%s)", event_id, name)
|
|
return state
|