Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
6.1KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # External UI
  4. # Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation; either version 2 of
  9. # the License, or any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. from sys import argv
  20. # ------------------------------------------------------------------------------------------------------------
  21. # Imports (Custom Stuff)
  22. from carla_shared import *
  23. # ------------------------------------------------------------------------------------------------------------
  24. # External UI
  25. class ExternalUI(object):
  26. def __init__(self):
  27. object.__init__(self)
  28. self.fQuitReceived = False
  29. if len(argv) > 1:
  30. self.fSampleRate = float(argv[1])
  31. self.fUiName = argv[2]
  32. self.fPipeClient = gCarla.utils.pipe_client_new(lambda s,msg: self.msgCallback(msg))
  33. else:
  34. self.fSampleRate = 44100.0
  35. self.fUiName = "TestUI"
  36. self.fPipeClient = None
  37. # -------------------------------------------------------------------
  38. # Public methods
  39. def ready(self):
  40. if self.fPipeClient is not None:
  41. # send empty line (just newline char)
  42. self.send([""])
  43. else:
  44. # testing, show UI only
  45. self.uiShow()
  46. def isRunning(self):
  47. if self.fPipeClient is not None:
  48. return gCarla.utils.pipe_client_is_running(self.fPipeClient)
  49. return False
  50. def idleExternalUI(self):
  51. if self.fPipeClient is not None:
  52. gCarla.utils.pipe_client_idle(self.fPipeClient)
  53. def closeExternalUI(self):
  54. if not self.fQuitReceived:
  55. self.send(["exiting"])
  56. if self.fPipeClient is not None:
  57. gCarla.utils.pipe_client_destroy(self.fPipeClient)
  58. self.fPipeClient = None
  59. # -------------------------------------------------------------------
  60. # Host DSP State
  61. def getSampleRate(self):
  62. return self.fSampleRate
  63. def sendControl(self, index, value):
  64. self.send(["control", index, value])
  65. def sendProgram(self, channel, bank, program):
  66. self.send(["program", channel, bank, program])
  67. def sendConfigure(self, key, value):
  68. self.send(["configure", key, value])
  69. def sendNote(self, onOff, channel, note, velocity):
  70. self.send(["note", onOff, channel, note, velocity])
  71. # -------------------------------------------------------------------
  72. # DSP Callbacks
  73. def dspParameterChanged(self, index, value):
  74. return
  75. def dspProgramChanged(self, channel, bank, program):
  76. return
  77. def dspStateChanged(self, key, value):
  78. return
  79. def dspNoteReceived(self, onOff, channel, note, velocity):
  80. return
  81. # -------------------------------------------------------------------
  82. # ExternalUI Callbacks
  83. def uiShow(self):
  84. return
  85. def uiHide(self):
  86. return
  87. def uiQuit(self):
  88. self.closeExternalUI()
  89. def uiTitleChanged(self, uiTitle):
  90. return
  91. # -------------------------------------------------------------------
  92. # Callback
  93. def msgCallback(self, msg):
  94. msg = charPtrToString(msg)
  95. #if not msg:
  96. #return
  97. if msg == "control":
  98. index = int(self.readlineblock())
  99. value = float(self.readlineblock())
  100. self.dspParameterChanged(index, value)
  101. elif msg == "program":
  102. channel = int(self.readlineblock())
  103. bank = int(self.readlineblock())
  104. program = int(self.readlineblock())
  105. self.dspProgramChanged(channel, bank, program)
  106. elif msg == "configure":
  107. key = self.readlineblock() #.replace("\r", "\n")
  108. value = self.readlineblock() #.replace("\r", "\n")
  109. self.dspStateChanged(key, value)
  110. elif msg == "note":
  111. onOff = bool(self.readlineblock() == "true")
  112. channel = int(self.readlineblock())
  113. note = int(self.readlineblock())
  114. velocity = int(self.readlineblock())
  115. self.dspNoteReceived(onOff, channel, note, velocity)
  116. elif msg == "show":
  117. self.uiShow()
  118. elif msg == "hide":
  119. self.uiHide()
  120. elif msg == "quit":
  121. self.fQuitReceived = True
  122. self.uiQuit()
  123. elif msg == "uiTitle":
  124. uiTitle = self.readlineblock() #.replace("\r", "\n")
  125. self.uiTitleChanged(uiTitle)
  126. else:
  127. print("unknown message: \"" + msg + "\"")
  128. # -------------------------------------------------------------------
  129. # Internal stuff
  130. def readlineblock(self):
  131. if self.fPipeClient is None:
  132. return ""
  133. return gCarla.utils.pipe_client_readlineblock(self.fPipeClient, 50)
  134. def send(self, lines):
  135. if self.fPipeClient is None or len(lines) == 0:
  136. return
  137. gCarla.utils.pipe_client_lock(self.fPipeClient)
  138. for line in lines:
  139. if line is None:
  140. line2 = "(null)"
  141. elif isinstance(line, str):
  142. line2 = line.replace("\n", "\r")
  143. elif isinstance(line, bool):
  144. line2 = "true" if line else "false"
  145. elif isinstance(line, int):
  146. line2 = "%i" % line
  147. elif isinstance(line, float):
  148. line2 = "%.10f" % line
  149. else:
  150. print("unknown data type to send:", type(line))
  151. return
  152. gCarla.utils.pipe_client_write_msg(self.fPipeClient, line2 + "\n")
  153. gCarla.utils.pipe_client_flush_and_unlock(self.fPipeClient)