diff --git a/light9/midifade/midifade.py b/light9/midifade/midifade.py --- a/light9/midifade/midifade.py +++ b/light9/midifade/midifade.py @@ -5,11 +5,11 @@ Read midi events, write fade levels to g import asyncio import logging import traceback -from typing import Dict +from typing import Dict, List import mido from rdfdb.syncedgraph.syncedgraph import SyncedGraph -from rdflib import URIRef +from rdflib import Literal, URIRef from light9 import networking from light9.namespaces import L9 @@ -20,13 +20,18 @@ from light9.showconfig import showUri mido.set_backend('alsa_midi.mido_backend') MAX_SEND_RATE = 20 +_lastSet = {} #Fader:value + def setFader(graph: SyncedGraph, ctx, fader: URIRef, strength: float): log.info(f'setFader(fader={fader}, strength={strength:.03f}') valueLit = decimalLiteral(round(strength, 3)) with graph.currentState() as g: fadeSet = g.value(fader, L9['setting']) + if fadeSet is None: + raise ValueError(f'fader {fader} has no :setting') graph.patchObject(ctx, fadeSet, L9['value'], valueLit) + _lastSet[fader] = strength def onMessage(graph: SyncedGraph, ctx: URIRef, m: Dict): @@ -42,24 +47,77 @@ def onMessage(graph: SyncedGraph, ctx: U 46: L9['show/dance2023/fadePage1f0'], }, 'bcf2000': { - 81: L9['show/dance2023/fadePage1f0'], - 82: L9['show/dance2023/fadePage1f1'], - 83: L9['show/dance2023/fadePage1f2'], - 84: L9['show/dance2023/fadePage1f3'], - 85: L9['show/dance2023/fadePage1f4'], - 86: L9['show/dance2023/fadePage1f5'], - 87: L9['show/dance2023/fadePage1f6'], - 88: L9['show/dance2023/fadePage1f7'], + 81: L9['show/dance2023/fader0'], + 82: L9['show/dance2023/fader1'], + 83: L9['show/dance2023/fader2'], + 84: L9['show/dance2023/fader3'], + 85: L9['show/dance2023/fader4'], + 86: L9['show/dance2023/fader5'], + 87: L9['show/dance2023/fader6'], + 88: L9['show/dance2023/fader7'], } }[m['dev']][m['control']] except KeyError: log.info(f'unknown control {m}') return - setFader(graph, ctx, fader, m['value'] / 127) + try: + setFader(graph, ctx, fader, m['value'] / 127) + except ValueError as e: + log.warning(f'{e!r} - ignoring') else: log.info(f'unhandled message {m}') +def reduceToLatestValue(ms: List[Dict]) -> List[Dict]: + merge = {} + for m in ms: + normal_key = tuple(sorted(dict((k, v) for k, v in m.items() if k != 'value'))) + merge[normal_key] = m + return merge.values() + + +class WriteBackFaders: + + def __init__(self, graph: SyncedGraph, bcf_out, getCurrentValue): + self.graph = graph + self.bcf_out = bcf_out + self.getCurrentValue = getCurrentValue + + def update(self): + try: + self._update() + except ValueError as e: + log.warning(repr(e)) + + def _update(self): + g = self.graph + mapping = g.value(L9['midiControl'], L9['map']) + if mapping is None: + raise ValueError('no :midiControl :map ?mapping') + midiDev = g.value(mapping, L9['midiDev']) + ourDev = 'bcf2000' + if midiDev != Literal(ourDev): + raise NotImplementedError(f'need {mapping} to have :midiDev {ourDev!r}') + fadePage = g.value(mapping, L9['outputs']) + nupdated=0 + faders = list(g.objects(fadePage, L9.fader)) + for f in faders: + column = int(g.value(f, L9.column).toPython()) + fset = g.value(f, L9.setting) + # could split this to a separate handler per fader + value = g.value(fset, L9.value).toPython() + hwcurrent = int(self.getCurrentValue(f) * 127) + hwgoal = int(value * 127) + if abs(hwcurrent - hwgoal) > 5: + midi_ctl_addr = column + 80 + self.sendToBcf(midi_ctl_addr, hwgoal) + nupdated+=1 + log.info(f'updated {nupdated} of {len(faders)} connected faders') + def sendToBcf(self, control, value): + msg = mido.Message('control_change', control=control, value=value) + self.bcf_out.send(msg) + + async def main(): logging.getLogger('autodepgraphapi').setLevel(logging.INFO) logging.getLogger('syncedgraph').setLevel(logging.INFO) @@ -80,7 +138,8 @@ async def main(): while not msgs.empty(): recents.append(msgs.get_nowait()) try: - onMessage(graph, ctx, recents[-1]) + for msg in reduceToLatestValue(recents): + onMessage(graph, ctx, msg) except Exception as e: traceback.print_exc() log.warning("error in onMessage- continuing anyway") @@ -98,11 +157,13 @@ async def main(): else: continue log.info(f'listening on input {inputName} {dev=}') - openPorts.append( - mido.open_input(# - inputName,# - callback=lambda message, dev=dev: onMessageMidoThread(dev, message)) - ) + openPorts.append(mido.open_input( # + inputName, # + callback=lambda message, dev=dev: onMessageMidoThread(dev, message))) + + bcf_out = mido.open_output('BCF2000:BCF2000 MIDI 1 28:0') + wb = WriteBackFaders(graph, bcf_out, getCurrentValue=lambda f: _lastSet.get(f, 0)) + graph.addHandler(wb.update) while True: await asyncio.sleep(1) diff --git a/show/dance2023/fade.n3 b/show/dance2023/fade.n3 --- a/show/dance2023/fade.n3 +++ b/show/dance2023/fade.n3 @@ -5,276 +5,38 @@ @prefix xsd: . :midiControl :map :midiControl0 . +show:faderset8 :effectAttr :strength; :value 0.00 . +show:faderset9 :effectAttr :strength; :value 0.00 . +:fadeset0 :value 0.520 . +:fadeset1 :value 0.571 . +:fadeset2 :value 0.580 . +:fadeset3 :value 0.589 . +:fadeset4 :value 0.597 . +:fadeset5 :value 0.606 . +:midiControl0 :inputs "mainSliders"; :midiDev "bcf2000"; :outputs show:fadePage0 . show:fadePage0 a :FadePage; rdfs:label "first"; :fader show:fader0, show:fader1, show:fader2, show:fader3, show:fader4, show:fader5, show:fader6, show:fader7 . -show:fadePage2 a :FadePage; rdfs:label "unnamed"; :fader show:fader40, show:fader41, show:fader42, show:fader43, show:fader44, show:fader45, show:fader46, show:fader47 . - -show:fadePage3 a :FadePage; rdfs:label "unnamed"; :fader show:fader48, show:fader49, show:fader50, show:fader51, show:fader52, show:fader53, show:fader54, show:fader55 . - -show:fadePage4 a :FadePage; rdfs:label "unnamed"; :fader show:fader56, show:fader57, show:fader58, show:fader59, show:fader60, show:fader61, show:fader62, show:fader63 . - -show:fadePage5 a :FadePage; rdfs:label "unnamed"; :fader show:fader64, show:fader65, show:fader66, show:fader67, show:fader68, show:fader69, show:fader70, show:fader71 . - -show:fadePage6 a :FadePage; rdfs:label "unnamed"; :fader show:fader72, show:fader73, show:fader74, show:fader75, show:fader76, show:fader77, show:fader78, show:fader79 . - -show:fadePage7 a :FadePage; rdfs:label "unnamed"; :fader show:fader80, show:fader81, show:fader82, show:fader83, show:fader84, show:fader85, show:fader86, show:fader87 . - -show:fader10 a :Fader; :column "3"; :setting show:faderset18 . - -show:fader11 a :Fader; :column "4"; :setting show:faderset19 . - -show:fader12 a :Fader; :column "5"; :setting show:faderset20 . - -show:fader13 a :Fader; :column "6"; :setting show:faderset21 . - -show:fader14 a :Fader; :column "7"; :setting show:faderset22 . - -show:fader15 a :Fader; :column "8"; :setting show:faderset23 . -show:fader16 :column "1"; :setting show:faderset8 . -show:fader17 :column "2"; :setting show:faderset9 . -show:fader18 :column "3"; :setting show:faderset10 . -show:fader19 :column "4"; :setting show:faderset11 . -show:fader20 :column "5"; :setting show:faderset12 . -show:fader21 :column "6"; :setting show:faderset13 . -show:fader22 :column "7"; :setting show:faderset14 . -show:fader23 :column "8"; :setting show:faderset15 . - -show:fader24 a :Fader; :column "1"; :setting show:faderset24 . - -show:fader25 a :Fader; :column "2"; :setting show:faderset25 . - -show:fader26 a :Fader; :column "3"; :setting show:faderset26 . - -show:fader27 a :Fader; :column "4"; :setting show:faderset27 . - -show:fader28 a :Fader; :column "5"; :setting show:faderset28 . - -show:fader29 a :Fader; :column "6"; :setting show:faderset29 . - -show:fader30 a :Fader; :column "7"; :setting show:faderset30 . - -show:fader31 a :Fader; :column "8"; :setting show:faderset31 . - -show:fader8 a :Fader; :column "1"; :setting show:faderset16 . - -show:fader9 a :Fader; :column "2"; :setting show:faderset17 . -:midiControl0 :inputs "mainSliders"; :midiDev "bcf2000"; :outputs show:fadePage1 . - -show:fadePage1 a :FadePage; rdfs:label "second"; :fader show:fader32, show:fader33, show:fader34, show:fader35, show:fader36, show:fader37, show:fader38, show:fader39 . - show:fader0 a :Fader; :column "1"; :effect effect:effect1; :setting show:faderset0 . show:fader1 a :Fader; :column "2"; :effect effect:effect6; :setting show:faderset1 . -show:fader2 a :Fader; :column "3"; :effect effect:effect7; :setting show:faderset2 . - -show:fader3 a :Fader; :column "4"; :setting show:faderset3 . - -show:fader32 a :Fader; :column "1"; :setting show:faderset32 . - -show:fader33 a :Fader; :column "2"; :setting show:faderset33 . - -show:fader34 a :Fader; :column "3"; :setting show:faderset34 . - -show:fader35 a :Fader; :column "4"; :setting show:faderset35 . - -show:fader36 a :Fader; :column "5"; :setting show:faderset36 . - -show:fader37 a :Fader; :column "6"; :setting show:faderset37 . - -show:fader38 a :Fader; :column "7"; :setting show:faderset38 . - -show:fader39 a :Fader; :column "8"; :setting show:faderset39 . +show:fader2 a :Fader; :column "3"; :effect effect:effect4; :setting show:faderset2 . -show:fader4 a :Fader; :column "5"; :setting show:faderset4 . - -show:fader40 a :Fader; :column "1"; :setting show:faderset40 . - -show:fader41 a :Fader; :column "2"; :setting show:faderset41 . - -show:fader42 a :Fader; :column "3"; :setting show:faderset42 . - -show:fader43 a :Fader; :column "4"; :setting show:faderset43 . - -show:fader44 a :Fader; :column "5"; :setting show:faderset44 . - -show:fader45 a :Fader; :column "6"; :setting show:faderset45 . - -show:fader46 a :Fader; :column "7"; :setting show:faderset46 . - -show:fader47 a :Fader; :column "8"; :setting show:faderset47 . - -show:fader48 a :Fader; :column "1"; :setting show:faderset48 . - -show:fader49 a :Fader; :column "2"; :setting show:faderset49 . +show:fader3 a :Fader; :column "4"; :effect effect:effect9; :setting show:faderset3 . -show:fader5 a :Fader; :column "6"; :setting show:faderset5 . - -show:fader50 a :Fader; :column "3"; :setting show:faderset50 . - -show:fader51 a :Fader; :column "4"; :setting show:faderset51 . - -show:fader52 a :Fader; :column "5"; :setting show:faderset52 . - -show:fader53 a :Fader; :column "6"; :setting show:faderset53 . - -show:fader54 a :Fader; :column "7"; :setting show:faderset54 . - -show:fader55 a :Fader; :column "8"; :setting show:faderset55 . - -show:fader56 a :Fader; :column "1"; :setting show:faderset56 . - -show:fader57 a :Fader; :column "2"; :setting show:faderset57 . - -show:fader58 a :Fader; :column "3"; :setting show:faderset58 . - -show:fader59 a :Fader; :column "4"; :setting show:faderset59 . +show:fader4 a :Fader; :column "5"; :effect effect:effect2; :setting show:faderset4 . -show:fader6 a :Fader; :column "7"; :setting show:faderset6 . - -show:fader60 a :Fader; :column "5"; :setting show:faderset60 . - -show:fader61 a :Fader; :column "6"; :setting show:faderset61 . - -show:fader62 a :Fader; :column "7"; :setting show:faderset62 . - -show:fader63 a :Fader; :column "8"; :setting show:faderset63 . +show:fader5 a :Fader; :column "6"; :effect effect:effect3; :setting show:faderset5 . -show:fader64 a :Fader; :column "1"; :setting show:faderset64 . - -show:fader65 a :Fader; :column "2"; :setting show:faderset65 . - -show:fader66 a :Fader; :column "3"; :setting show:faderset66 . - -show:fader67 a :Fader; :column "4"; :setting show:faderset67 . - -show:fader68 a :Fader; :column "5"; :setting show:faderset68 . - -show:fader69 a :Fader; :column "6"; :setting show:faderset69 . +show:fader6 a :Fader; :column "7"; :effect effect:effect8; :setting :fadeset0, :fadeset1, :fadeset2, :fadeset3, :fadeset4, :fadeset5, show:faderset6 . show:fader7 a :Fader; :column "8"; :setting show:faderset7 . - -show:fader70 a :Fader; :column "7"; :setting show:faderset70 . - -show:fader71 a :Fader; :column "8"; :setting show:faderset71 . - -show:fader72 a :Fader; :column "1"; :setting show:faderset72 . - -show:fader73 a :Fader; :column "2"; :setting show:faderset73 . - -show:fader74 a :Fader; :column "3"; :setting show:faderset74 . - -show:fader75 a :Fader; :column "4"; :setting show:faderset75 . - -show:fader76 a :Fader; :column "5"; :setting show:faderset76 . - -show:fader77 a :Fader; :column "6"; :setting show:faderset77 . - -show:fader78 a :Fader; :column "7"; :setting show:faderset78 . - -show:fader79 a :Fader; :column "8"; :setting show:faderset79 . - -show:fader80 a :Fader; :column "1"; :setting show:faderset80 . - -show:fader81 a :Fader; :column "2"; :setting show:faderset81 . - -show:fader82 a :Fader; :column "3"; :setting show:faderset82 . - -show:fader83 a :Fader; :column "4"; :setting show:faderset83 . - -show:fader84 a :Fader; :column "5"; :setting show:faderset84 . - -show:fader85 a :Fader; :column "6"; :setting show:faderset85 . - -show:fader86 a :Fader; :column "7"; :setting show:faderset86 . - -show:fader87 a :Fader; :column "8"; :setting show:faderset87 . -show:faderset0 :effectAttr :strength; :value 1.00 . -show:faderset1 :effectAttr :strength; :value 0.208 . -show:faderset10 :effectAttr :strength; :value 0.00 . -show:faderset11 :effectAttr :strength; :value 0.00 . -show:faderset12 :effectAttr :strength; :value 0.00 . -show:faderset13 :effectAttr :strength; :value 0.00 . -show:faderset14 :effectAttr :strength; :value 0.00 . -show:faderset15 :effectAttr :strength; :value 0.00 . -show:faderset16 :effectAttr :strength; :value 0.00 . -show:faderset17 :effectAttr :strength; :value 0.00 . -show:faderset18 :effectAttr :strength; :value 0.00 . -show:faderset19 :effectAttr :strength; :value 0.00 . -show:faderset2 :effectAttr :strength; :value 0.357 . -show:faderset20 :effectAttr :strength; :value 0.00 . -show:faderset21 :effectAttr :strength; :value 0.00 . -show:faderset22 :effectAttr :strength; :value 0.00 . -show:faderset23 :effectAttr :strength; :value 0.00 . -show:faderset24 :effectAttr :strength; :value 0.00 . -show:faderset25 :effectAttr :strength; :value 0.00 . -show:faderset26 :effectAttr :strength; :value 0.00 . -show:faderset27 :effectAttr :strength; :value 0.00 . -show:faderset28 :effectAttr :strength; :value 0.00 . -show:faderset29 :effectAttr :strength; :value 0.00 . -show:faderset3 :effectAttr :strength; :value 0.250 . -show:faderset30 :effectAttr :strength; :value 0.00 . -show:faderset31 :effectAttr :strength; :value 0.00 . -show:faderset32 :effectAttr :strength; :value 0.00 . -show:faderset33 :effectAttr :strength; :value 0.00 . -show:faderset34 :effectAttr :strength; :value 0.00 . -show:faderset35 :effectAttr :strength; :value 0.00 . -show:faderset36 :effectAttr :strength; :value 0.00 . -show:faderset37 :effectAttr :strength; :value 0.00 . -show:faderset38 :effectAttr :strength; :value 0.530 . -show:faderset39 :effectAttr :strength; :value 0.00 . -show:faderset4 :effectAttr :strength; :value 0.00 . -show:faderset40 :effectAttr :strength; :value 0.00 . -show:faderset41 :effectAttr :strength; :value 0.00 . -show:faderset42 :effectAttr :strength; :value 0.00 . -show:faderset43 :effectAttr :strength; :value 0.00 . -show:faderset44 :effectAttr :strength; :value 0.00 . -show:faderset45 :effectAttr :strength; :value 0.00 . -show:faderset46 :effectAttr :strength; :value 0.00 . -show:faderset47 :effectAttr :strength; :value 0.00 . -show:faderset48 :effectAttr :strength; :value 0.00 . -show:faderset49 :effectAttr :strength; :value 0.00 . -show:faderset5 :effectAttr :strength; :value 0.403 . -show:faderset50 :effectAttr :strength; :value 0.00 . -show:faderset51 :effectAttr :strength; :value 0.00 . -show:faderset52 :effectAttr :strength; :value 0.00 . -show:faderset53 :effectAttr :strength; :value 0.00 . -show:faderset54 :effectAttr :strength; :value 0.413 . -show:faderset55 :effectAttr :strength; :value 0.200 . -show:faderset56 :effectAttr :strength; :value 0.00 . -show:faderset57 :effectAttr :strength; :value 0.00 . -show:faderset58 :effectAttr :strength; :value 0.00 . -show:faderset59 :effectAttr :strength; :value 0.00 . -show:faderset6 :effectAttr :strength; :value 0.00 . -show:faderset60 :effectAttr :strength; :value 0.00 . -show:faderset61 :effectAttr :strength; :value 0.00 . -show:faderset62 :effectAttr :strength; :value 0.00 . -show:faderset63 :effectAttr :strength; :value 0.00 . -show:faderset64 :effectAttr :strength; :value 0.00 . -show:faderset65 :effectAttr :strength; :value 0.00 . -show:faderset66 :effectAttr :strength; :value 0.00 . -show:faderset67 :effectAttr :strength; :value 0.00 . -show:faderset68 :effectAttr :strength; :value 0.00 . -show:faderset69 :effectAttr :strength; :value 0.00 . -show:faderset7 :effectAttr :strength; :value 0.00 . -show:faderset70 :effectAttr :strength; :value 0.00 . -show:faderset71 :effectAttr :strength; :value 0.00 . -show:faderset72 :effectAttr :strength; :value 0.00 . -show:faderset73 :effectAttr :strength; :value 0.00 . -show:faderset74 :effectAttr :strength; :value 0.00 . -show:faderset75 :effectAttr :strength; :value 0.00 . -show:faderset76 :effectAttr :strength; :value 0.00 . -show:faderset77 :effectAttr :strength; :value 0.00 . -show:faderset78 :effectAttr :strength; :value 0.00 . -show:faderset79 :effectAttr :strength; :value 0.00 . -show:faderset8 :effectAttr :strength; :value 0.00 . -show:faderset80 :effectAttr :strength; :value 0.00 . -show:faderset81 :effectAttr :strength; :value 0.00 . -show:faderset82 :effectAttr :strength; :value 0.00 . -show:faderset83 :effectAttr :strength; :value 0.00 . -show:faderset84 :effectAttr :strength; :value 0.00 . -show:faderset85 :effectAttr :strength; :value 0.00 . -show:faderset86 :effectAttr :strength; :value 0.00 . -show:faderset87 :effectAttr :strength; :value 0.00 . -show:faderset9 :effectAttr :strength; :value 0.00 . +show:faderset0 :effectAttr :strength; :value 0.425 . +show:faderset1 :effectAttr :strength; :value 0.126 . +show:faderset2 :effectAttr :strength; :value 0.126 . +show:faderset3 :effectAttr :strength; :value 1.00 . +show:faderset4 :effectAttr :strength; :value 0.094 . +show:faderset5 :effectAttr :strength; :value 0.386 . +show:faderset6 :effectAttr :strength; :value 0.287 . +show:faderset7 :effectAttr :strength; :value 0.173 .