diff --git a/light9/effect/sequencer/eval_faders.py b/light9/effect/sequencer/eval_faders.py --- a/light9/effect/sequencer/eval_faders.py +++ b/light9/effect/sequencer/eval_faders.py @@ -1,25 +1,40 @@ import asyncio +from dataclasses import dataclass import logging import time -from typing import Callable, Coroutine, List, cast +from typing import Callable, Coroutine, List, Optional, cast +from light9.collector.collector import uriTail +from light9.typedgraph import typedValue from rdfdb.syncedgraph.syncedgraph import SyncedGraph from rdflib import URIRef from light9.effect import effecteval from light9.effect.sequencer import Note -from light9.effect.settings import DeviceSettings +from light9.effect.settings import DeviceSettings, EffectSettings from light9.effect.simple_outputs import SimpleOutputs from light9.metrics import metrics from light9.namespaces import L9, RDF -from light9.newtypes import EffectAttr, NoteUri, UnixTime +from light9.newtypes import EffectAttr, EffectUri, NoteUri, UnixTime +from rdflib.term import Node log = logging.getLogger('seq.fader') +@dataclass +class Fader: + graph: SyncedGraph + uri: URIRef + effect: EffectUri + setEffectAttr: EffectAttr + + value: Optional[float]=None # mutable + + def __post_init__(self): + self.ee = effecteval.EffectEval2(self.graph, self.effect) + class FaderEval: """peer to Sequencer, but this one takes the current :Fader settings -> sendToCollector - The current faders become Notes in here, for more code reuse. """ def __init__(self, graph: SyncedGraph, @@ -28,12 +43,11 @@ class FaderEval: self.graph = graph self.sendToCollector = sendToCollector - # Notes without times- always on - self.notes: List[Note] = [] + self.faders: List[Fader] = [] - self.simpleOutputs = SimpleOutputs(self.graph) + # self.simpleOutputs = SimpleOutputs(self.graph) log.info('fader adds handler') - self.graph.addHandler(self.compileGraph) + self.graph.addHandler(self._compile) self.lastLoopSucceeded = False # self.codeWatcher = CodeWatcher(onChange=self.onCodeChange) @@ -46,44 +60,43 @@ class FaderEval: def onCodeChange(self): log.debug('seq.onCodeChange') - self.graph.addHandler(self.compileGraph) + self.graph.addHandler(self._compile) #self.updateLoop() @metrics('compile_graph_fader').time() - def compileGraph(self) -> None: + def _compile(self) -> None: """rebuild our data from the graph""" - self.notes = [] + self.faders = [] for fader in self.graph.subjects(RDF.type, L9['Fader']): - def compileFader() -> Note: - return self.compileFader(cast(URIRef, 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, cast(URIRef, fader), effect, setAttr)) - self.notes.append(compileFader()) - # if self.notes: - # asyncio.create_task(self.startUpdating()) - - - @metrics('compile_fader').time() - def compileFader(self, fader: URIRef) -> Note: - return Note(self.graph, cast(NoteUri, fader), - timed=False) + # this could go in a second, smaller addHandler call to avoid rebuilding Fader objs constantly + for f in self.faders: + f.value = typedValue(float, self.graph, f.uri, L9['value']) def computeOutput(self) -> DeviceSettings: - notesSettings = [] + notesSettings:List[DeviceSettings] = [] now = UnixTime(time.time()) - for note in self.notes: - effectSettings, report = note.outputCurrent() + 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)]) - if effectSettings.s[EffectAttr(L9['strength'])]==0: - continue + print(f'{effectSettings=}') + notesSettings.append(f.ee.compute(effectSettings)) - ee = effecteval.EffectEval(self.graph, note.effectClass, self.simpleOutputs) - deviceSettings, report = ee.outputFromEffect( - effectSettings, - songTime=now, # probably wrong - noteTime=now, # wrong - ) - if deviceSettings: - notesSettings.append(deviceSettings) + # ee = effecteval.EffectEval(self.graph, f.effectClass, self.simpleOutputs) + # deviceSettings, report = ee.outputFromEffect( + # effectSettings, + # songTime=now, # probably wrong + # noteTime=now, # wrong + # ) + # log.info(f' 𝅘𝅥𝅮 {uriTail(f.uri)}: {effectSettings=} -> {deviceSettings=}') + # if deviceSettings: + # notesSettings.append(deviceSettings) return DeviceSettings.merge(self.graph, notesSettings)