import logging
import time
from dataclasses import dataclass
from typing import List, Optional, cast
from prometheus_client import Summary
from light9.effect.effect_function_library import EffectFunctionLibrary
from light9.effect.effecteval2 import EffectEval2
from rdfdb import SyncedGraph
from rdflib import URIRef
from rdflib.term import Node
from light9.effect.settings import DeviceSettings, EffectSettings
from light9.metrics import metrics
from light9.namespaces import L9, RDF
from light9.newtypes import EffectAttr, EffectUri, UnixTime
from light9.typedgraph import typedValue
log = logging.getLogger('seq.fader')
COMPILE=Summary('compile_graph_fader', '')
@dataclass
class Fader:
graph: SyncedGraph
lib: EffectFunctionLibrary
uri: URIRef
effect: EffectUri
setEffectAttr: EffectAttr
value: Optional[float]=None # mutable
def __post_init__(self):
self.ee = EffectEval2(self.graph, self.effect, self.lib)
class FaderEval:
"""peer to Sequencer, but this one takes the current :Fader settings -> sendToCollector
"""
def __init__(self,
graph: SyncedGraph,
lib: EffectFunctionLibrary
):
self.graph = graph
self.lib = lib
self.faders: List[Fader] = []
self.graph.addHandler(self._compile)
self.lastLoopSucceeded = False
@COMPILE.time()
def _compile(self) -> None:
"""rebuild our data from the graph"""
self.faders = []
for fader in self.graph.subjects(RDF.type, L9['Fader']):
effect = typedValue(EffectUri, self.graph, fader, L9['effect'])
setting = typedValue(Node, self.graph, fader, L9['setting'])
setAttr = typedValue(EffectAttr, self.graph, setting, L9['effectAttr'])
self.faders.append(Fader(self.graph, self.lib, cast(URIRef, fader), effect, setAttr))
# this could go in a second, smaller addHandler call to avoid rebuilding Fader objs constantly
for f in self.faders:
setting = typedValue(Node, self.graph, f.uri, L9['setting'])
f.value = typedValue(float, self.graph, setting, L9['value'])
def computeOutput(self) -> DeviceSettings:
faderEffectOutputs: List[DeviceSettings] = []
now = UnixTime(time.time())
for f in self.faders:
if f.value is None:
raise TypeError('f.value should be set by now')
effectSettings = EffectSettings(self.graph, [(f.effect, f.setEffectAttr, f.value)])
ds = f.ee.compute(now, effectSettings)
faderEffectOutputs.append(ds)
return DeviceSettings.merge(self.graph, faderEffectOutputs)