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.

751 lines
27KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla plugin host (plugin UI)
  4. # Copyright (C) 2013 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 GPL.txt file
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. from time import sleep
  20. # ------------------------------------------------------------------------------------------------------------
  21. # Imports (Custom Stuff)
  22. from carla_host import *
  23. from externalui import ExternalUI
  24. # ------------------------------------------------------------------------------------------------------------
  25. # Helper object
  26. class PluginStoreInfo(object):
  27. __slots__ = [
  28. 'pluginInfo',
  29. 'pluginRealName',
  30. 'audioCountInfo',
  31. 'midiCountInfo',
  32. 'parameterCount',
  33. 'parameterCountInfo',
  34. 'parameterInfoS',
  35. 'parameterDataS',
  36. 'parameterRangeS',
  37. 'parameterValueS',
  38. 'programCount',
  39. 'programCurrent',
  40. 'programNameS',
  41. 'midiProgramCount',
  42. 'midiProgramCurrent',
  43. 'midiProgramDataS',
  44. 'peaks'
  45. ]
  46. # ------------------------------------------------------------------------------------------------------------
  47. # Host Plugin object
  48. class PluginHost(object):
  49. def __init__(self, sampleRate):
  50. object.__init__(self)
  51. self.fSupportedFileExts = ""
  52. self.fBufferSize = 0
  53. self.fSampleRate = sampleRate
  54. self.fLastError = ""
  55. self.fIsRunning = True
  56. self.fPluginsInfo = []
  57. def _add(self, pluginId):
  58. if len(self.fPluginsInfo) != pluginId:
  59. return
  60. info = PluginStoreInfo()
  61. info.pluginInfo = PyCarlaPluginInfo
  62. info.pluginRealName = ""
  63. info.audioCountInfo = PyCarlaPortCountInfo
  64. info.midiCountInfo = PyCarlaPortCountInfo
  65. info.parameterCount = 0
  66. info.parameterCountInfo = PyCarlaPortCountInfo
  67. info.parameterInfoS = []
  68. info.parameterDataS = []
  69. info.parameterRangeS = []
  70. info.parameterValueS = []
  71. info.programCount = 0
  72. info.programCurrent = -1
  73. info.programNameS = []
  74. info.midiProgramCount = 0
  75. info.midiProgramCurrent = -1
  76. info.midiProgramDataS = []
  77. info.peaks = [0.0, 0.0, 0.0, 0.0]
  78. self.fPluginsInfo.append(info)
  79. def _set_pluginInfo(self, pluginId, info):
  80. self.fPluginsInfo[pluginId].pluginInfo = info
  81. def _set_pluginName(self, pluginId, name):
  82. self.fPluginsInfo[pluginId].pluginInfo['name'] = name
  83. def _set_pluginRealName(self, pluginId, realName):
  84. self.fPluginsInfo[pluginId].pluginRealName = realName
  85. def _set_audioCountInfo(self, pluginId, info):
  86. self.fPluginsInfo[pluginId].audioCountInfo = info
  87. def _set_midiCountInfo(self, pluginId, info):
  88. self.fPluginsInfo[pluginId].midiCountInfo = info
  89. def _set_parameterCountInfo(self, pluginId, count, info):
  90. self.fPluginsInfo[pluginId].parameterCount = count
  91. self.fPluginsInfo[pluginId].parameterCountInfo = info
  92. # clear
  93. self.fPluginsInfo[pluginId].parameterInfoS = []
  94. self.fPluginsInfo[pluginId].parameterDataS = []
  95. self.fPluginsInfo[pluginId].parameterRangeS = []
  96. self.fPluginsInfo[pluginId].parameterValueS = []
  97. # add placeholders
  98. for x in range(count):
  99. self.fPluginsInfo[pluginId].parameterInfoS.append(PyCarlaParameterInfo)
  100. self.fPluginsInfo[pluginId].parameterDataS.append(PyParameterData)
  101. self.fPluginsInfo[pluginId].parameterRangeS.append(PyParameterRanges)
  102. self.fPluginsInfo[pluginId].parameterValueS.append(0.0)
  103. def _set_programCount(self, pluginId, count):
  104. self.fPluginsInfo[pluginId].programCount = count
  105. # clear
  106. self.fPluginsInfo[pluginId].programNameS = []
  107. # add placeholders
  108. for x in range(count):
  109. self.fPluginsInfo[pluginId].programNameS.append("")
  110. def _set_midiProgramCount(self, pluginId, count):
  111. self.fPluginsInfo[pluginId].midiProgramCount = count
  112. # clear
  113. self.fPluginsInfo[pluginId].midiProgramDataS = []
  114. # add placeholders
  115. for x in range(count):
  116. self.fPluginsInfo[pluginId].midiProgramDataS.append(PyMidiProgramData)
  117. def _set_parameterInfoS(self, pluginId, paramIndex, info):
  118. if paramIndex < self.fPluginsInfo[pluginId].parameterCount:
  119. self.fPluginsInfo[pluginId].parameterInfoS[paramIndex] = info
  120. def _set_parameterDataS(self, pluginId, paramIndex, data):
  121. if paramIndex < self.fPluginsInfo[pluginId].parameterCount:
  122. self.fPluginsInfo[pluginId].parameterDataS[paramIndex] = data
  123. def _set_parameterRangeS(self, pluginId, paramIndex, ranges):
  124. if paramIndex < self.fPluginsInfo[pluginId].parameterCount:
  125. self.fPluginsInfo[pluginId].parameterRangeS[paramIndex] = ranges
  126. def _set_parameterValueS(self, pluginId, paramIndex, value):
  127. if paramIndex < self.fPluginsInfo[pluginId].parameterCount:
  128. self.fPluginsInfo[pluginId].parameterValueS[paramIndex] = value
  129. def _set_parameterDefault(self, pluginId, paramIndex, value):
  130. if paramIndex < self.fPluginsInfo[pluginId].parameterCount:
  131. self.fPluginsInfo[pluginId].parameterRangeS[paramIndex]['def'] = value
  132. def _set_parameterMidiChannel(self, pluginId, paramIndex, channel):
  133. if paramIndex < self.fPluginsInfo[pluginId].parameterCount:
  134. self.fPluginsInfo[pluginId].parameterDataS[paramIndex]['midiChannel'] = channel
  135. def _set_parameterMidiCC(self, pluginId, paramIndex, cc):
  136. if paramIndex < self.fPluginsInfo[pluginId].parameterCount:
  137. self.fPluginsInfo[pluginId].parameterDataS[paramIndex]['midiCC'] = cc
  138. def _set_currentProgram(self, pluginId, pIndex):
  139. self.fPluginsInfo[pluginId].programCurrent = pIndex
  140. def _set_currentMidiProgram(self, pluginId, mpIndex):
  141. self.fPluginsInfo[pluginId].midiProgramCurrent = mpIndex
  142. def _set_programNameS(self, pluginId, pIndex, name):
  143. if pIndex < self.fPluginsInfo[pluginId].programCount:
  144. self.fPluginsInfo[pluginId].programNameS[pIndex] = name
  145. def _set_midiProgramDataS(self, pluginId, mpIndex, data):
  146. if mpIndex < self.fPluginsInfo[pluginId].midiProgramCount:
  147. self.fPluginsInfo[pluginId].midiProgramDataS[mpIndex] = data
  148. def _set_peaks(self, pluginId, in1, in2, out1, out2):
  149. self.fPluginsInfo[pluginId].peaks = [in1, in2, out1, out2]
  150. # -------------------------------------------------------------------
  151. def get_complete_license_text(self):
  152. return ""
  153. def get_supported_file_extensions(self):
  154. return self.fSupportedFileExts
  155. # -------------------------------------------------------------------
  156. def get_engine_driver_count(self):
  157. return 1
  158. def get_engine_driver_name(self, index):
  159. return "Plugin"
  160. def get_engine_driver_device_names(self, index):
  161. return []
  162. def get_engine_driver_device_info(self, index, name):
  163. return PyEngineDriverDeviceInfo
  164. # -------------------------------------------------------------------
  165. def get_internal_plugin_count(self):
  166. return 0
  167. def get_internal_plugin_info(self, index):
  168. return None
  169. # -------------------------------------------------------------------
  170. def engine_init(self, driverName, clientName):
  171. return True
  172. def engine_close(self):
  173. return True
  174. def engine_idle(self):
  175. if Carla.gui.idleExternalUI():
  176. return
  177. self.fIsRunning = False
  178. Carla.gui.d_uiQuit()
  179. def is_engine_running(self):
  180. return self.fIsRunning
  181. def set_engine_about_to_close(self):
  182. pass
  183. def set_engine_callback(self, func):
  184. pass
  185. def set_engine_option(self, option, value, valueStr):
  186. Carla.gui.send(["set_engine_option", option, value, valueStr])
  187. # -------------------------------------------------------------------
  188. def set_file_callback(self, func):
  189. pass
  190. def load_file(self, filename):
  191. Carla.gui.send(["load_file", filename])
  192. return True
  193. def load_project(self, filename):
  194. Carla.gui.send(["load_project", filename])
  195. return True
  196. def save_project(self, filename):
  197. Carla.gui.send(["save_project", filename])
  198. return True
  199. # -------------------------------------------------------------------
  200. def patchbay_connect(self, portIdA, portIdB):
  201. Carla.gui.send(["patchbay_connect", portIdA, portIdB])
  202. return True
  203. def patchbay_disconnect(self, connectionId):
  204. Carla.gui.send(["patchbay_disconnect", connectionId])
  205. return True
  206. def patchbay_refresh(self):
  207. Carla.gui.send(["patchbay_refresh"])
  208. return True
  209. # -------------------------------------------------------------------
  210. def transport_play(self):
  211. Carla.gui.send(["transport_play"])
  212. def transport_pause(self):
  213. Carla.gui.send(["transport_pause"])
  214. def transport_relocate(self, frame):
  215. Carla.gui.send(["transport_relocate"])
  216. def get_current_transport_frame(self):
  217. return 0
  218. def get_transport_info(self):
  219. return PyCarlaTransportInfo
  220. # -------------------------------------------------------------------
  221. def add_plugin(self, btype, ptype, filename, name, label, extraPtr):
  222. Carla.gui.send(["add_plugin", btype, ptype, filename, name, label])
  223. return True
  224. def remove_plugin(self, pluginId):
  225. Carla.gui.send(["remove_plugin", pluginId])
  226. return True
  227. def remove_all_plugins(self):
  228. Carla.gui.send(["remove_all_plugins"])
  229. return True
  230. def rename_plugin(self, pluginId, newName):
  231. Carla.gui.send(["rename_plugin", pluginId, newName])
  232. return newName
  233. def clone_plugin(self, pluginId):
  234. Carla.gui.send(["clone_plugin", pluginId])
  235. return True
  236. def replace_plugin(self, pluginId):
  237. Carla.gui.send(["replace_plugin", pluginId])
  238. return True
  239. def switch_plugins(self, pluginIdA, pluginIdB):
  240. Carla.gui.send(["switch_plugins", pluginIdA, pluginIdB])
  241. return True
  242. # -------------------------------------------------------------------
  243. def load_plugin_state(self, pluginId, filename):
  244. Carla.gui.send(["load_plugin_state", pluginId, filename])
  245. return True
  246. def save_plugin_state(self, pluginId, filename):
  247. Carla.gui.send(["save_plugin_state", pluginId, filename])
  248. return True
  249. # -------------------------------------------------------------------
  250. def get_plugin_info(self, pluginId):
  251. return self.fPluginsInfo[pluginId].pluginInfo
  252. def get_audio_port_count_info(self, pluginId):
  253. return self.fPluginsInfo[pluginId].audioCountInfo
  254. def get_midi_port_count_info(self, pluginId):
  255. return self.fPluginsInfo[pluginId].midiCountInfo
  256. def get_parameter_count_info(self, pluginId):
  257. return self.fPluginsInfo[pluginId].parameterCountInfo
  258. def get_parameter_info(self, pluginId, parameterId):
  259. return self.fPluginsInfo[pluginId].parameterInfoS[parameterId]
  260. def get_parameter_scalepoint_info(self, pluginId, parameterId, scalePointId):
  261. return PyCarlaScalePointInfo
  262. # -------------------------------------------------------------------
  263. def get_parameter_data(self, pluginId, parameterId):
  264. return self.fPluginsInfo[pluginId].parameterDataS[parameterId]
  265. def get_parameter_ranges(self, pluginId, parameterId):
  266. return self.fPluginsInfo[pluginId].parameterRangeS[parameterId]
  267. def get_midi_program_data(self, pluginId, midiProgramId):
  268. return self.fPluginsInfo[pluginId].midiProgramDataS[midiProgramId]
  269. def get_custom_data(self, pluginId, customDataId):
  270. return PyCustomData
  271. def get_chunk_data(self, pluginId):
  272. return ""
  273. # -------------------------------------------------------------------
  274. def get_parameter_count(self, pluginId):
  275. return self.fPluginsInfo[pluginId].parameterCount
  276. def get_program_count(self, pluginId):
  277. return self.fPluginsInfo[pluginId].programCount
  278. def get_midi_program_count(self, pluginId):
  279. return self.fPluginsInfo[pluginId].midiProgramCount
  280. def get_custom_data_count(self, pluginId):
  281. return 0
  282. # -------------------------------------------------------------------
  283. def get_parameter_text(self, pluginId, parameterId, value):
  284. return ""
  285. def get_program_name(self, pluginId, programId):
  286. return self.fPluginsInfo[pluginId].programNameS[programId]
  287. def get_midi_program_name(self, pluginId, midiProgramId):
  288. return self.fPluginsInfo[pluginId].midiProgramDataS[midiProgramId]['label']
  289. def get_real_plugin_name(self, pluginId):
  290. return self.fPluginsInfo[pluginId].pluginRealName
  291. # -------------------------------------------------------------------
  292. def get_current_program_index(self, pluginId):
  293. return self.fPluginsInfo[pluginId].programCurrent
  294. def get_current_midi_program_index(self, pluginId):
  295. return self.fPluginsInfo[pluginId].midiProgramCurrent
  296. def get_default_parameter_value(self, pluginId, parameterId):
  297. return self.fPluginsInfo[pluginId].parameterRangeS[parameterId]['def']
  298. def get_current_parameter_value(self, pluginId, parameterId):
  299. return self.fPluginsInfo[pluginId].parameterValueS[parameterId]
  300. def get_input_peak_value(self, pluginId, isLeft):
  301. return self.fPluginsInfo[pluginId].peaks[0 if isLeft else 1]
  302. def get_output_peak_value(self, pluginId, isLeft):
  303. return self.fPluginsInfo[pluginId].peaks[2 if isLeft else 3]
  304. # -------------------------------------------------------------------
  305. def set_option(self, pluginId, option, yesNo):
  306. Carla.gui.send(["set_option", pluginId, option, yesNo])
  307. def set_active(self, pluginId, onOff):
  308. Carla.gui.send(["set_active", pluginId, onOff])
  309. def set_drywet(self, pluginId, value):
  310. Carla.gui.send(["set_drywet", pluginId, value])
  311. def set_volume(self, pluginId, value):
  312. Carla.gui.send(["set_volume", pluginId, value])
  313. def set_balance_left(self, pluginId, value):
  314. Carla.gui.send(["set_balance_left", pluginId, value])
  315. def set_balance_right(self, pluginId, value):
  316. Carla.gui.send(["set_balance_right", pluginId, value])
  317. def set_panning(self, pluginId, value):
  318. Carla.gui.send(["set_panning", pluginId, value])
  319. def set_ctrl_channel(self, pluginId, channel):
  320. Carla.gui.send(["set_ctrl_channel", pluginId, channel])
  321. # -------------------------------------------------------------------
  322. def set_parameter_value(self, pluginId, parameterId, value):
  323. Carla.gui.send(["set_parameter_value", pluginId, parameterId, value])
  324. def set_parameter_midi_channel(self, pluginId, parameterId, channel):
  325. Carla.gui.send(["set_parameter_midi_channel", pluginId, parameterId, channel])
  326. def set_parameter_midi_cc(self, pluginId, parameterId, cc):
  327. Carla.gui.send(["set_parameter_midi_cc", pluginId, parameterId, cc])
  328. def set_program(self, pluginId, programId):
  329. Carla.gui.send(["set_program", pluginId, programId])
  330. def set_midi_program(self, pluginId, midiProgramId):
  331. Carla.gui.send(["set_midi_program", pluginId, midiProgramId])
  332. def set_custom_data(self, pluginId, type_, key, value):
  333. Carla.gui.send(["set_custom_data", pluginId, type_, key, value])
  334. def set_chunk_data(self, pluginId, chunkData):
  335. Carla.gui.send(["set_chunk_data", pluginId, chunkData])
  336. # -------------------------------------------------------------------
  337. def prepare_for_save(self, pluginId):
  338. Carla.gui.send(["prepare_for_save", pluginId])
  339. def send_midi_note(self, pluginId, channel, note, velocity):
  340. Carla.gui.send(["send_midi_note", pluginId, channel, note, velocity])
  341. def show_custom_ui(self, pluginId, yesNo):
  342. Carla.gui.send(["show_custom_ui", pluginId, yesNo])
  343. # -------------------------------------------------------------------
  344. def get_buffer_size(self):
  345. return self.fBufferSize
  346. def get_sample_rate(self):
  347. return self.fSampleRate
  348. def get_last_error(self):
  349. return self.fLastError
  350. def get_host_osc_url_tcp(self):
  351. return ""
  352. def get_host_osc_url_udp(self):
  353. return ""
  354. # ------------------------------------------------------------------------------------------------------------
  355. # Main Window
  356. class CarlaMiniW(HostWindow, ExternalUI):
  357. def __init__(self):
  358. HostWindow.__init__(self, None)
  359. ExternalUI.__init__(self)
  360. if False:
  361. from carla_patchbay import CarlaPatchbayW
  362. self.fContainer = CarlaPatchbayW(self)
  363. else:
  364. from carla_rack import CarlaRackW
  365. self.fContainer = CarlaRackW(self)
  366. self.setupContainer(False)
  367. self.setWindowTitle(self.fUiName)
  368. self.showUiIfTesting()
  369. # -------------------------------------------------------------------
  370. # ExternalUI Callbacks
  371. def d_uiShow(self):
  372. self.show()
  373. def d_uiHide(self):
  374. self.hide()
  375. def d_uiQuit(self):
  376. self.close()
  377. app.quit()
  378. def d_uiTitleChanged(self, uiTitle):
  379. self.setWindowTitle(uiTitle)
  380. # -------------------------------------------------------------------
  381. # Qt events
  382. def closeEvent(self, event):
  383. self.closeExternalUI()
  384. HostWindow.closeEvent(self, event)
  385. # -------------------------------------------------------------------
  386. # Custom idler
  387. def idleExternalUI(self):
  388. while True:
  389. if self.fPipeRecv is None:
  390. return True
  391. try:
  392. msg = self.fPipeRecv.readline().strip()
  393. except IOError:
  394. return False
  395. if not msg:
  396. return True
  397. elif msg.startswith("PEAKS_"):
  398. pluginId = int(msg.replace("PEAKS_", ""))
  399. in1, in2, out1, out2 = [float(i) for i in self.fPipeRecv.readline().strip().split(":")]
  400. Carla.host._set_peaks(pluginId, in1, in2, out1, out2)
  401. elif msg.startswith("PARAMVAL_"):
  402. pluginId, paramId = [int(i) for i in msg.replace("PARAMVAL_", "").split(":")]
  403. paramValue = float(self.fPipeRecv.readline().strip())
  404. Carla.host._set_parameterValueS(pluginId, paramId, paramValue)
  405. elif msg.startswith("ENGINE_CALLBACK_"):
  406. action = int(msg.replace("ENGINE_CALLBACK_", ""))
  407. pluginId = int(self.fPipeRecv.readline().strip())
  408. value1 = int(self.fPipeRecv.readline().strip())
  409. value2 = int(self.fPipeRecv.readline().strip())
  410. value3 = float(self.fPipeRecv.readline().strip())
  411. valueStr = self.fPipeRecv.readline().strip().replace("\r", "\n")
  412. if action == ENGINE_CALLBACK_PLUGIN_RENAMED:
  413. Carla.host._set_pluginName(pluginId, valueStr)
  414. elif action == ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED:
  415. Carla.host._set_parameterValueS(pluginId, value1, value3)
  416. elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED:
  417. Carla.host._set_parameterDefault(pluginId, value1, value3)
  418. elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED:
  419. Carla.host._set_parameterMidiCC(pluginId, value1, value2)
  420. elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED:
  421. Carla.host._set_parameterMidiChannel(pluginId, value1, value2)
  422. elif action == ENGINE_CALLBACK_PROGRAM_CHANGED:
  423. Carla.host._set_currentProgram(pluginId, value1)
  424. elif action == ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED:
  425. Carla.host._set_currentMidiProgram(pluginId, value1)
  426. engineCallback(None, action, pluginId, value1, value2, value3, valueStr)
  427. elif msg.startswith("PLUGIN_INFO_"):
  428. pluginId = int(msg.replace("PLUGIN_INFO_", ""))
  429. Carla.host._add(pluginId)
  430. type_, category, hints, uniqueId, optsAvail, optsEnabled = [int(i) for i in self.fPipeRecv.readline().strip().split(":")]
  431. filename = self.fPipeRecv.readline().strip().replace("\r", "\n")
  432. name = self.fPipeRecv.readline().strip().replace("\r", "\n")
  433. iconName = self.fPipeRecv.readline().strip().replace("\r", "\n")
  434. realName = self.fPipeRecv.readline().strip().replace("\r", "\n")
  435. label = self.fPipeRecv.readline().strip().replace("\r", "\n")
  436. maker = self.fPipeRecv.readline().strip().replace("\r", "\n")
  437. copyright = self.fPipeRecv.readline().strip().replace("\r", "\n")
  438. pinfo = {
  439. 'type': type_,
  440. 'category': category,
  441. 'hints': hints,
  442. 'optionsAvailable': optsAvail,
  443. 'optionsEnabled': optsEnabled,
  444. 'filename': filename,
  445. 'name': name,
  446. 'label': label,
  447. 'maker': maker,
  448. 'copyright': copyright,
  449. 'iconName': iconName,
  450. 'patchbayClientId': 0,
  451. 'uniqueId': uniqueId
  452. }
  453. Carla.host._set_pluginInfo(pluginId, pinfo)
  454. Carla.host._set_pluginRealName(pluginId, realName)
  455. elif msg.startswith("AUDIO_COUNT_"):
  456. pluginId, ins, outs = [int(i) for i in msg.replace("AUDIO_COUNT_", "").split(":")]
  457. Carla.host._set_audioCountInfo(pluginId, {'ins': ins, 'outs': outs})
  458. elif msg.startswith("MIDI_COUNT_"):
  459. pluginId, ins, outs = [int(i) for i in msg.replace("MIDI_COUNT_", "").split(":")]
  460. Carla.host._set_midiCountInfo(pluginId, {'ins': ins, 'outs': outs})
  461. elif msg.startswith("PARAMETER_COUNT_"):
  462. pluginId, ins, outs, count = [int(i) for i in msg.replace("PARAMETER_COUNT_", "").split(":")]
  463. Carla.host._set_parameterCountInfo(pluginId, count, {'ins': ins, 'outs': outs})
  464. elif msg.startswith("PARAMETER_DATA_"):
  465. pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_DATA_", "").split(":")]
  466. paramType, paramHints, midiChannel, midiCC = [int(i) for i in self.fPipeRecv.readline().strip().split(":")]
  467. paramName = self.fPipeRecv.readline().strip().replace("\r", "\n")
  468. paramUnit = self.fPipeRecv.readline().strip().replace("\r", "\n")
  469. paramInfo = {
  470. 'name': paramName,
  471. 'symbol': "",
  472. 'unit': paramUnit,
  473. 'scalePointCount': 0,
  474. }
  475. Carla.host._set_parameterInfoS(pluginId, paramId, paramInfo)
  476. paramData = {
  477. 'type': paramType,
  478. 'hints': paramHints,
  479. 'index': paramId,
  480. 'rindex': -1,
  481. 'midiCC': midiCC,
  482. 'midiChannel': midiChannel
  483. }
  484. Carla.host._set_parameterDataS(pluginId, paramId, paramData)
  485. elif msg.startswith("PARAMETER_RANGES_"):
  486. pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_RANGES_", "").split(":")]
  487. def_, min_, max_, step, stepSmall, stepLarge = [float(i) for i in self.fPipeRecv.readline().strip().split(":")]
  488. paramRanges = {
  489. 'def': def_,
  490. 'min': min_,
  491. 'max': max_,
  492. 'step': step,
  493. 'stepSmall': stepSmall,
  494. 'stepLarge': stepLarge
  495. }
  496. Carla.host._set_parameterRangeS(pluginId, paramId, paramRanges)
  497. elif msg.startswith("PROGRAM_COUNT_"):
  498. pluginId, count, current = [int(i) for i in msg.replace("PROGRAM_COUNT_", "").split(":")]
  499. Carla.host._set_programCount(pluginId, count)
  500. Carla.host._set_currentProgram(pluginId, current)
  501. elif msg.startswith("PROGRAM_NAME_"):
  502. pluginId, progId = [int(i) for i in msg.replace("PROGRAM_NAME_", "").split(":")]
  503. progName = self.fPipeRecv.readline().strip().replace("\r", "\n")
  504. Carla.host._set_programNameS(pluginId, progId, progName)
  505. elif msg.startswith("MIDI_PROGRAM_COUNT_"):
  506. pluginId, count, current = [int(i) for i in msg.replace("MIDI_PROGRAM_COUNT_", "").split(":")]
  507. Carla.host._set_midiProgramCount(pluginId, count)
  508. Carla.host._set_currentMidiProgram(pluginId, current)
  509. elif msg.startswith("MIDI_PROGRAM_DATA_"):
  510. pluginId, midiProgId = [int(i) for i in msg.replace("MIDI_PROGRAM_DATA_", "").split(":")]
  511. bank, program = [int(i) for i in self.fPipeRecv.readline().strip().split(":")]
  512. name = self.fPipeRecv.readline().strip().replace("\r", "\n")
  513. Carla.host._set_midiProgramDataS(pluginId, midiProgId, {'bank': bank, 'program': program, 'name': name})
  514. elif msg == "show":
  515. self.d_uiShow()
  516. elif msg == "hide":
  517. self.d_uiHide()
  518. elif msg == "quit":
  519. self.fQuitReceived = True
  520. self.d_uiQuit()
  521. elif msg == "uiTitle":
  522. uiTitle = self.fPipeRecv.readline().strip().replace("\r", "\n")
  523. self.d_uiTitleChanged(uiTitle)
  524. else:
  525. print("unknown message: \"" + msg + "\"")
  526. return True
  527. # ------------------------------------------------------------------------------------------------------------
  528. # Main
  529. if __name__ == '__main__':
  530. # -------------------------------------------------------------
  531. # App initialization
  532. app = CarlaApplication()
  533. # -------------------------------------------------------------
  534. # Set-up custom signal handling
  535. setUpSignals()
  536. # -------------------------------------------------------------
  537. # Init plugin host data
  538. Carla.isControl = False
  539. Carla.isLocal = True
  540. Carla.isPlugin = True
  541. # -------------------------------------------------------------
  542. # Create GUI first
  543. Carla.gui = CarlaMiniW()
  544. # -------------------------------------------------------------
  545. # Init plugin host now
  546. Carla.host = PluginHost(Carla.gui.d_getSampleRate())
  547. initHost("Carla-Plugin")
  548. engineCallback(None, ENGINE_CALLBACK_ENGINE_STARTED, 0, ENGINE_PROCESS_MODE_CONTINUOUS_RACK, ENGINE_TRANSPORT_MODE_PLUGIN, 0.0, "Plugin")
  549. # -------------------------------------------------------------
  550. # App-Loop
  551. sys.exit(app.exec_())