Mercurial > code > home > repos > light9
view src/light9/midifade/eventqueue.py @ 2389:0e90dd50e8c4
midifade: improve the midi-event-skip behavior
author | drewp@bigasterisk.com |
---|---|
date | Tue, 14 May 2024 12:16:53 -0700 |
parents | 3cd80b266561 |
children | 485148ef5686 |
line wrap: on
line source
import asyncio from dataclasses import dataclass import logging import traceback log = logging.getLogger() @dataclass class Event: dev: str type: str control: int value: int def __repr__(self): return f"<Event {self.dev}/{self.type}/{self.control}->{self.value}>" class EventQueue: """midi events come in fast; graph consumes them slower""" def __init__(self, MAX_SEND_RATE: float, onMessage) -> None: self.MAX_SEND_RATE = MAX_SEND_RATE self.onMessage = onMessage self.newEvents: asyncio.Queue[Event] = asyncio.Queue() def callbackFor(self, dev): mainThreadLoop = asyncio.get_running_loop() def cb(message): # this is running in mido's thread d = message.dict() ev = Event(dev, d['type'], d['control'], d['value']) log.info(f'enqueue {ev} {"*" * ev.value}') mainThreadLoop.call_soon_threadsafe( self.newEvents.put_nowait, ev, ) return cb async def run(self): while True: recentEvents = [await self.newEvents.get()] while not self.newEvents.empty(): recentEvents.append(self.newEvents.get_nowait()) log.info(f'{recentEvents=}') try: for msg in latestEventPerControl(recentEvents): log.info(f'handle {msg=}') await self.onMessage(msg) except Exception: traceback.print_exc() log.warning("error in onMessage- continuing anyway") await asyncio.sleep(1 / self.MAX_SEND_RATE) def latestEventPerControl(evs: list[Event]) -> list[Event]: ret = [] seenControl = set() for ev in reversed(evs): c = (ev.dev, ev.control) if c in seenControl: continue seenControl.add(c) ret.append(ev) ret.reverse() return ret