def __init__(self, name, data): devices.Device.__init__(self, name, data) self.closed = False self.service = None self.plock = threading.RLock() if '/' in name or '\\' in name: raise ValueError("Path sep in name") self.serviceDir = os.path.join(directories.vardir, "hardlinep2p", name) os.makedirs(self.serviceDir, exist_ok=True) if data.get('device.service', '').strip() and data.get( 'device.title', '').strip(): def f(): try: import hardline self.service = hardline.Service( os.path.join(self.serviceDir, 'service.cert'), data["device.service"], int(data.get('device.port', '80')), { 'title': data.get("device.title", '').replace( '{{host}}', socket.gethostname()) }) except Exception: self.handleException() workers.do(f)
def __init__(self, name, data): devices.Device.__init__(self, name, data) self.widgets = [] self.synth = None def f(): try: if len(name) == 1: self.handleError( 'Single letter names may not work correctly. JACK in general may have subpar performace with this plugin badly configured.' ) self.synthLock = threading.Lock() self.synth = scullery.fluidsynth.FluidSynth( soundfont=data.get("device.soundfont", "").strip(), jackClientName=name, connectOutput=data.get("device.connectOutput", "").strip()) for i in range(0, 16): try: inst = "" inst = data.get("device.ch" + str(i) + "instrument", "") bank = None if ':' in inst: bank, inst = inst.split(":") bank = int(bank.strip()) inst = inst.strip() try: inst = int(inst) except: pass if inst: self.synth.setInstrument(i, inst, bank=bank) except: self.handleError("Error setting instrument:" + inst + " for channel " + str(i) + "\n" + traceback.format_exc()) connectMidi = data.get("device.connectMidi", "").strip().replace(":", '_').replace( "[", '').replace("]", '').replace(" ", '') messagebus.subscribe("/midi/" + connectMidi, self.onMidiMsg) for i in range(16): x = widgets.Button() x.attach(self.makeWidgetHandler(i)) self.widgets.append(x) except: self.handleException() workers.do(f)
def pgc(self, c, v): def f(): if not self.synth: return with self.synthLock: self.synth.programChange(c, v) workers.do(f)
def bend(self, c, v): def f(): if not self.synth: return with self.synthLock: self.synth.pitchBend(c, v) workers.do(f)
def cc(self, c, p, v): def f(): if not self.synth: return with self.synthLock: self.synth.cc(c, p, v) workers.do(f)
def noteOff(self, c, p): def f(): if not self.synth: return with self.synthLock: self.synth.noteOff(c, p) workers.do(f)
def onConnect(self): self.kaithemInterface().onConnect() self.kaithemInterface().print("Connected to gateway") def f(): time.sleep(3) self.kaithemInterface().print( "serial round-trip latency(avg,min,max): "+str(self.testLatency())) workers.do(f) return super().onConnect()
def __init__(self, name, data): devices.Device.__init__(self, name, data) try: self.ps = JackVoicePipeline( name, data.get("device.keywords", "hello\nworld")) self.ps.controller = weakref.ref(self) def f(): try: self.ps.start(timeout=60) except: self.handleException() workers.do(f) except: self.handleException()
def _onActive(self): global unacknowledged global active with lock: cleanup() _unacknowledged[self.id] = weakref.ref(self) unacknowledged = _unacknowledged.copy() _active[self.id] = weakref.ref(self) active = _active.copy() s = calcNextBeep() if s: # Sound drivers can actually use tagpoints, this was causing a # deadlock with the tag's lock in the __del__ function GCing some # other tag. I don't quite understand it but this should break the loop def f(): # Ondemand to avoid circular import from . import sound beepDevice = file['all']['soundcard'] sound.playSound(s, handle="kaithem_sys_main_alarm", output=beepDevice) api.send(['shouldRefresh']) workers.do(f) if self.priority in ("error", "critical"): logger.error("Alarm " + self.name + " ACTIVE") messagebus.postMessage("/system/notifications/errors", "Alarm " + self.name + " is active") if self.priority in ("warning"): messagebus.postMessage("/system/notifications/warnings", "Alarm " + self.name + " is active") logger.warning("Alarm " + self.name + " ACTIVE") else: logger.info("Alarm " + self.name + " active") if self.priority in ("info"): messagebus.postMessage("/system/notifications", "Alarm " + self.name + " is active")
## Code outside the data string, and the setup and action blocks is ignored ## If manually editing, you must reload the code. Delete the resource timestamp so kaithem knows it's new __data__=""" {continual: false, enable: true, once: true, priority: interactive, rate-limit: 0.0, resource-timestamp: 1610570841501375, resource-type: event} """ __trigger__='False' if __name__=='__setup__': #This code runs once when the event loads. It also runs when you save the event during the test compile #and may run multiple times when kaithem boots due to dependancy resolution __doc__='This event should have an error associated with it. If it does not, report an bugge!' from src import workers def raise_an_exception(): raise RuntimeError("This exception raised to test what happens when a function in the thread pool errors") workers.do(raise_an_exception) def eventAction(): pass