Changeset - 81b48e21ba46
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 20 months ago 2023-06-01 21:47:35
drewp@bigasterisk.com
multi device supt
1 file changed with 41 insertions and 22 deletions:
0 comments (0 inline, 0 general)
light9/midifade/midifade.py
Show inline comments
 
#!bin/python
 
"""
 
Read midi events, write fade levels to graph
 
"""
 
import asyncio
 
import logging
 
import traceback
 
from typing import Dict
 

	
 
import mido
 
from rdfdb.syncedgraph.syncedgraph import SyncedGraph
 
from rdflib import URIRef
 

	
 
from light9 import networking
 
from light9.namespaces import L9
 
from light9.newtypes import decimalLiteral
 
from light9.run_local import log
 
from light9.showconfig import showUri
 

	
 
mido.set_backend('alsa_midi.mido_backend')
 
MAX_SEND_RATE = 20
 

	
 

	
 
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'])
 
    graph.patchObject(ctx, fadeSet, L9['value'], valueLit)
 

	
 

	
 
def onMessage(graph: SyncedGraph, ctx: URIRef, m: mido.Message):
 
    md = m.dict()
 
    if md['type'] == 'active_sensing':
 
def onMessage(graph: SyncedGraph, ctx: URIRef, m: Dict):
 
    if m['type'] == 'active_sensing':
 
        return
 
    if m.is_cc():
 
        if md['control'] == 81: setFader(graph, ctx, L9['show/dance2023/fadePage1f0'], md['value'] / 127)
 
        if md['control'] == 82: setFader(graph, ctx, L9['show/dance2023/fadePage1f1'], md['value'] / 127)
 
        if md['control'] == 83: setFader(graph, ctx, L9['show/dance2023/fadePage1f2'], md['value'] / 127)
 
        if md['control'] == 84: setFader(graph, ctx, L9['show/dance2023/fadePage1f3'], md['value'] / 127)
 
        if md['control'] == 85: setFader(graph, ctx, L9['show/dance2023/fadePage1f4'], md['value'] / 127)
 
        if md['control'] == 86: setFader(graph, ctx, L9['show/dance2023/fadePage1f5'], md['value'] / 127)
 
        if md['control'] == 87: setFader(graph, ctx, L9['show/dance2023/fadePage1f6'], md['value'] / 127)
 
        if md['control'] == 88: setFader(graph, ctx, L9['show/dance2023/fadePage1f7'], md['value'] / 127)
 
        else:
 
            log.info(f'unhandled cc message {md}')
 
    if m['type'] == 'control_change':
 

	
 
        try:
 
            fader = {
 
                'quneo': {
 
                    44: L9['show/dance2023/fadePage1f0'],
 
                    45: L9['show/dance2023/fadePage1f0'],
 
                    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'],
 
                }
 
            }[m['dev']][m['control']]
 
        except KeyError:
 
            log.info(f'unknown control {m}')
 
            return
 
        setFader(graph, ctx, fader, m['value'] / 127)
 
    else:
 
        log.info(f'unhandled message {md}')
 
        log.info(f'unhandled message {m}')
 

	
 

	
 
async def main():
 
    logging.getLogger('autodepgraphapi').setLevel(logging.INFO)
 
    logging.getLogger('syncedgraph').setLevel(logging.INFO)
 
    logging.getLogger('graphedit').setLevel(logging.INFO)
 

	
 
    graph = SyncedGraph(networking.rdfdb.url, "midifade")
 
    ctx = URIRef(showUri() + '/fade')
 

	
 
    msgs = asyncio.Queue()
 
    loop = asyncio.get_event_loop()
 

	
 
    def onMessageMidoThread(message):
 
        loop.call_soon_threadsafe(msgs.put_nowait, message)
 
    def onMessageMidoThread(dev, message):
 
        loop.call_soon_threadsafe(msgs.put_nowait, message.dict() | {'dev': dev})
 

	
 
    async def reader():
 
        while True:
 
            recents = [await msgs.get()]
 
            while not msgs.empty():
 
                recents.append(msgs.get_nowait())
 
            try:
 
                onMessage(graph, ctx, recents[-1])
 
            except Exception as e:
 
                traceback.print_exc()
 
                log.warning("error in onMessage- continuing anyway")
 
            await asyncio.sleep(1 / MAX_SEND_RATE)
 

	
 
    asyncio.create_task(reader())
 
    log.info(f'{mido.get_input_names()}')
 
    port = mido.open_input(
 
        #'Keystation:Keystation MIDI 1 20:0',
 
        'BCF2000:BCF2000 MIDI 1 20:0',
 
         callback=onMessageMidoThread)
 

	
 
    for inputName in mido.get_input_names():
 
        if inputName.startswith('Keystation'):
 
            dev = "keystation"
 
        elif inputName.startswith('BCF2000'):
 
            dev = 'bcf2000'
 
        elif inputName.startswith('QUNEO'):
 
            dev = 'quneo'
 
        else:
 
            continue
 
        log.info(f'listening on input {inputName} {dev=}')
 
        port = mido.open_input(inputName, callback=lambda message: onMessageMidoThread(dev, message))
 

	
 
    while True:
 
        await asyncio.sleep(1)
 

	
 

	
 
if __name__ == '__main__':
 
    asyncio.run(main())
0 comments (0 inline, 0 general)