#!/usr/bin/env python3 # -*- coding: utf-8 -*- # External UI # Copyright (C) 2013-2014 Filipe Coelho # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # For a full copy of the GNU General Public License see the doc/GPL.txt file. # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) from carla_shared import * # ------------------------------------------------------------------------------------------------------------ # External UI class ExternalUI(object): def __init__(self): object.__init__(self) self.fQuitReceived = False if len(sys.argv) > 1: self.fSampleRate = float(sys.argv[1]) self.fUiName = sys.argv[2] self.fPipeClient = gCarla.utils.pipe_client_new(lambda s,msg: self.msgCallback(msg)) else: self.fSampleRate = 44100.0 self.fUiName = "TestUI" self.fPipeClient = None # ------------------------------------------------------------------- # Public methods def ready(self): if self.fPipeClient is None: # testing, show UI only self.uiShow() def isRunning(self): if self.fPipeClient is not None: return gCarla.utils.pipe_client_is_running(self.fPipeClient) return False def idleExternalUI(self): if self.fPipeClient is not None: gCarla.utils.pipe_client_idle(self.fPipeClient) def closeExternalUI(self): if self.fPipeClient is None: return if not self.fQuitReceived: self.send(["exiting"]) gCarla.utils.pipe_client_destroy(self.fPipeClient) self.fPipeClient = None # ------------------------------------------------------------------- # Host DSP State def getSampleRate(self): return self.fSampleRate def sendControl(self, index, value): self.send(["control", index, value]) def sendProgram(self, channel, bank, program): self.send(["program", channel, bank, program]) def sendConfigure(self, key, value): self.send(["configure", key, value]) def sendNote(self, onOff, channel, note, velocity): self.send(["note", onOff, channel, note, velocity]) # ------------------------------------------------------------------- # DSP Callbacks def dspParameterChanged(self, index, value): return def dspProgramChanged(self, channel, bank, program): return def dspStateChanged(self, key, value): return def dspNoteReceived(self, onOff, channel, note, velocity): return # ------------------------------------------------------------------- # ExternalUI Callbacks def uiShow(self): return def uiHide(self): return def uiQuit(self): self.closeExternalUI() def uiTitleChanged(self, uiTitle): return # ------------------------------------------------------------------- # Callback def msgCallback(self, msg): msg = charPtrToString(msg) #if not msg: #return if msg == "control": index = int(self.readlineblock()) value = float(self.readlineblock()) self.dspParameterChanged(index, value) elif msg == "program": channel = int(self.readlineblock()) bank = int(self.readlineblock()) program = int(self.readlineblock()) self.dspProgramChanged(channel, bank, program) elif msg == "configure": key = self.readlineblock() #.replace("\r", "\n") value = self.readlineblock() #.replace("\r", "\n") self.dspStateChanged(key, value) elif msg == "note": onOff = bool(self.readlineblock() == "true") channel = int(self.readlineblock()) note = int(self.readlineblock()) velocity = int(self.readlineblock()) self.dspNoteReceived(onOff, channel, note, velocity) elif msg == "show": self.uiShow() elif msg == "hide": self.uiHide() elif msg == "quit": self.fQuitReceived = True self.uiQuit() elif msg == "uiTitle": uiTitle = self.readlineblock() #.replace("\r", "\n") self.uiTitleChanged(uiTitle) else: print("unknown message: \"" + msg + "\"") # ------------------------------------------------------------------- # Internal stuff def readlineblock(self): if self.fPipeClient is None: return "" return gCarla.utils.pipe_client_readlineblock(self.fPipeClient, 5000) def send(self, lines): if self.fPipeClient is None or len(lines) == 0: return gCarla.utils.pipe_client_lock(self.fPipeClient) # this must never fail, we need to unlock at the end try: for line in lines: if line is None: line2 = "(null)" elif isinstance(line, str): line2 = line.replace("\n", "\r") elif isinstance(line, bool): line2 = "true" if line else "false" elif isinstance(line, int): line2 = "%i" % line elif isinstance(line, float): line2 = "%.10f" % line else: print("unknown data type to send:", type(line)) return gCarla.utils.pipe_client_write_msg(self.fPipeClient, line2 + "\n") except: pass gCarla.utils.pipe_client_flush_and_unlock(self.fPipeClient)