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.

666 lines
28KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla host code
  4. # Copyright (C) 2011-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 doc/GPL.txt file.
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. try:
  20. from PyQt5.QtWidgets import QApplication, QMainWindow
  21. except:
  22. from PyQt4.QtGui import QApplication, QMainWindow
  23. # ------------------------------------------------------------------------------------------------------------
  24. # Imports (Custom)
  25. import ui_carla_host
  26. from carla_database import *
  27. from carla_settings import *
  28. from carla_widgets import *
  29. # ------------------------------------------------------------------------------------------------------------
  30. # Dummy widget
  31. class CarlaDummyW(object):
  32. def __init__(self, parent):
  33. object.__init__(self)
  34. # -----------------------------------------------------------------
  35. def getPluginCount(self):
  36. return 0
  37. def getPlugin(self, pluginId):
  38. return None
  39. # -----------------------------------------------------------------
  40. def addPlugin(self, pluginId, isProjectLoading):
  41. pass
  42. def removePlugin(self, pluginId):
  43. pass
  44. def renamePlugin(self, pluginId, newName):
  45. pass
  46. def removeAllPlugins(self):
  47. pass
  48. # -----------------------------------------------------------------
  49. def setParameterValue(self, pluginId, index, value):
  50. pass
  51. def setParameterDefault(self, pluginId, index, value):
  52. pass
  53. def setParameterMidiChannel(self, pluginId, index, channel):
  54. pass
  55. def setParameterMidiCC(self, pluginId, index, cc):
  56. pass
  57. # -----------------------------------------------------------------
  58. def setProgram(self, pluginId, index):
  59. pass
  60. def setMidiProgram(self, pluginId, index):
  61. pass
  62. # -----------------------------------------------------------------
  63. def noteOn(self, pluginId, channel, note, velocity):
  64. pass
  65. def noteOff(self, pluginId, channel, note):
  66. pass
  67. # -----------------------------------------------------------------
  68. def setGuiState(self, pluginId, state):
  69. pass
  70. # -----------------------------------------------------------------
  71. def updateInfo(self, pluginId):
  72. pass
  73. def reloadInfo(self, pluginId):
  74. pass
  75. def reloadParameters(self, pluginId):
  76. pass
  77. def reloadPrograms(self, pluginId):
  78. pass
  79. def reloadAll(self, pluginId):
  80. pass
  81. # -----------------------------------------------------------------
  82. def patchbayClientAdded(self, clientId, clientIcon, clientName):
  83. pass
  84. def patchbayClientRemoved(self, clientId, clientName):
  85. pass
  86. def patchbayClientRenamed(self, clientId, newClientName):
  87. pass
  88. def patchbayPortAdded(self, clientId, portId, portFlags, portName):
  89. pass
  90. def patchbayPortRemoved(self, groupId, portId, fullPortName):
  91. pass
  92. def patchbayPortRenamed(self, groupId, portId, newPortName):
  93. pass
  94. def patchbayConnectionAdded(self, connectionId, portOutId, portInId):
  95. pass
  96. def patchbayConnectionRemoved(self, connectionId):
  97. pass
  98. def patchbayIconChanged(self, clientId, clientIcon):
  99. pass
  100. # -----------------------------------------------------------------
  101. def idleFast(self):
  102. pass
  103. def idleSlow(self):
  104. pass
  105. # ------------------------------------------------------------------------------------------------------------
  106. # Host Window
  107. class HostWindow(QMainWindow):
  108. # signals
  109. DebugCallback = pyqtSignal(int, int, int, float, str)
  110. PluginAddedCallback = pyqtSignal(int)
  111. PluginRemovedCallback = pyqtSignal(int)
  112. PluginRenamedCallback = pyqtSignal(int, str)
  113. ParameterValueChangedCallback = pyqtSignal(int, int, float)
  114. ParameterDefaultChangedCallback = pyqtSignal(int, int, float)
  115. ParameterMidiChannelChangedCallback = pyqtSignal(int, int, int)
  116. ParameterMidiCcChangedCallback = pyqtSignal(int, int, int)
  117. ProgramChangedCallback = pyqtSignal(int, int)
  118. MidiProgramChangedCallback = pyqtSignal(int, int)
  119. NoteOnCallback = pyqtSignal(int, int, int, int)
  120. NoteOffCallback = pyqtSignal(int, int, int)
  121. ShowGuiCallback = pyqtSignal(int, int)
  122. UpdateCallback = pyqtSignal(int)
  123. ReloadInfoCallback = pyqtSignal(int)
  124. ReloadParametersCallback = pyqtSignal(int)
  125. ReloadProgramsCallback = pyqtSignal(int)
  126. ReloadAllCallback = pyqtSignal(int)
  127. PatchbayClientAddedCallback = pyqtSignal(int, int, str)
  128. PatchbayClientRemovedCallback = pyqtSignal(int, str)
  129. PatchbayClientRenamedCallback = pyqtSignal(int, str)
  130. PatchbayPortAddedCallback = pyqtSignal(int, int, int, str)
  131. PatchbayPortRemovedCallback = pyqtSignal(int, int, str)
  132. PatchbayPortRenamedCallback = pyqtSignal(int, int, str)
  133. PatchbayConnectionAddedCallback = pyqtSignal(int, int, int)
  134. PatchbayConnectionRemovedCallback = pyqtSignal(int)
  135. PatchbayIconChangedCallback = pyqtSignal(int, int)
  136. BufferSizeChangedCallback = pyqtSignal(int)
  137. SampleRateChangedCallback = pyqtSignal(float)
  138. NSM_AnnounceCallback = pyqtSignal(str)
  139. NSM_OpenCallback = pyqtSignal(str)
  140. NSM_SaveCallback = pyqtSignal()
  141. ErrorCallback = pyqtSignal(str)
  142. QuitCallback = pyqtSignal()
  143. SIGTERM = pyqtSignal()
  144. SIGUSR1 = pyqtSignal()
  145. def __init__(self, parent):
  146. QMainWindow.__init__(self, parent)
  147. self.ui = ui_carla_host.Ui_CarlaHostW()
  148. self.ui.setupUi(self)
  149. if False:
  150. Carla.gui = self
  151. self.fContainer = CarlaDummyW(self)
  152. # -------------------------------------------------------------
  153. # Set callback
  154. Carla.host.set_engine_callback(EngineCallback)
  155. # -------------------------------------------------------------
  156. # Internal stuff
  157. self.fIdleTimerFast = 0
  158. self.fIdleTimerSlow = 0
  159. self.fIsProjectLoading = False
  160. self.fLadspaRdfNeedsUpdate = True
  161. self.fLadspaRdfList = []
  162. # -------------------------------------------------------------
  163. # Connect actions to functions
  164. #self.connect(self.ui.act_file_new, SIGNAL("triggered()"), SLOT("slot_fileNew()"))
  165. #self.connect(self.ui.act_file_open, SIGNAL("triggered()"), SLOT("slot_fileOpen()"))
  166. #self.connect(self.ui.act_file_save, SIGNAL("triggered()"), SLOT("slot_fileSave()"))
  167. #self.connect(self.ui.act_file_save_as, SIGNAL("triggered()"), SLOT("slot_fileSaveAs()"))
  168. ##self.connect(self.ui.act_file_export_lv2, SIGNAL("triggered()"), SLOT("slot_fileExportLv2Preset()"))
  169. #self.connect(self.ui.act_engine_start, SIGNAL("triggered()"), SLOT("slot_engineStart()"))
  170. #self.connect(self.ui.act_engine_stop, SIGNAL("triggered()"), SLOT("slot_engineStop()"))
  171. self.ui.act_plugin_add.triggered.connect(self.slot_pluginAdd)
  172. self.ui.act_plugin_add2.triggered.connect(self.slot_pluginAdd)
  173. self.ui.act_plugin_remove_all.triggered.connect(self.slot_pluginRemoveAll)
  174. #self.connect(self.ui.act_plugins_enable, SIGNAL("triggered()"), SLOT("slot_pluginsEnable()"))
  175. #self.connect(self.ui.act_plugins_disable, SIGNAL("triggered()"), SLOT("slot_pluginsDisable()"))
  176. #self.connect(self.ui.act_plugins_panic, SIGNAL("triggered()"), SLOT("slot_pluginsDisable()"))
  177. #self.connect(self.ui.act_plugins_volume100, SIGNAL("triggered()"), SLOT("slot_pluginsVolume100()"))
  178. #self.connect(self.ui.act_plugins_mute, SIGNAL("triggered()"), SLOT("slot_pluginsMute()"))
  179. #self.connect(self.ui.act_plugins_wet100, SIGNAL("triggered()"), SLOT("slot_pluginsWet100()"))
  180. #self.connect(self.ui.act_plugins_bypass, SIGNAL("triggered()"), SLOT("slot_pluginsBypass()"))
  181. #self.connect(self.ui.act_plugins_center, SIGNAL("triggered()"), SLOT("slot_pluginsCenter()"))
  182. #self.connect(self.ui.act_transport_play, SIGNAL("triggered(bool)"), SLOT("slot_transportPlayPause(bool)"))
  183. #self.connect(self.ui.act_transport_stop, SIGNAL("triggered()"), SLOT("slot_transportStop()"))
  184. #self.connect(self.ui.act_transport_backwards, SIGNAL("triggered()"), SLOT("slot_transportBackwards()"))
  185. #self.connect(self.ui.act_transport_forwards, SIGNAL("triggered()"), SLOT("slot_transportForwards()"))
  186. #self.ui.act_canvas_arrange.setEnabled(False) # TODO, later
  187. #self.connect(self.ui.act_canvas_arrange, SIGNAL("triggered()"), SLOT("slot_canvasArrange()"))
  188. #self.connect(self.ui.act_canvas_refresh, SIGNAL("triggered()"), SLOT("slot_canvasRefresh()"))
  189. #self.connect(self.ui.act_canvas_zoom_fit, SIGNAL("triggered()"), SLOT("slot_canvasZoomFit()"))
  190. #self.connect(self.ui.act_canvas_zoom_in, SIGNAL("triggered()"), SLOT("slot_canvasZoomIn()"))
  191. #self.connect(self.ui.act_canvas_zoom_out, SIGNAL("triggered()"), SLOT("slot_canvasZoomOut()"))
  192. #self.connect(self.ui.act_canvas_zoom_100, SIGNAL("triggered()"), SLOT("slot_canvasZoomReset()"))
  193. #self.connect(self.ui.act_canvas_print, SIGNAL("triggered()"), SLOT("slot_canvasPrint()"))
  194. #self.connect(self.ui.act_canvas_save_image, SIGNAL("triggered()"), SLOT("slot_canvasSaveImage()"))
  195. self.ui.act_settings_configure.triggered.connect(self.slot_configureCarla)
  196. self.ui.act_help_about.triggered.connect(self.slot_aboutCarla)
  197. self.ui.act_help_about_qt.triggered.connect(self.slot_aboutQt)
  198. #self.connect(self.ui.splitter, SIGNAL("splitterMoved.connect(self.slot_splitterMoved()"))
  199. #self.connect(self.ui.cb_disk, SIGNAL("currentIndexChanged.connect(self.slot_diskFolderChanged)
  200. #self.connect(self.ui.b_disk_add, SIGNAL("clicked()"), SLOT("slot_diskFolderAdd()"))
  201. #self.connect(self.ui.b_disk_remove, SIGNAL("clicked()"), SLOT("slot_diskFolderRemove()"))
  202. #self.connect(self.ui.fileTreeView, SIGNAL("doubleClicked(QModelIndex)"), SLOT("slot_fileTreeDoubleClicked(QModelIndex)"))
  203. #self.connect(self.ui.miniCanvasPreview, SIGNAL("miniCanvasMoved(double, double)"), SLOT("slot_miniCanvasMoved(double, double)"))
  204. #self.connect(self.ui.graphicsView.horizontalScrollBar(), SIGNAL("valueChanged.connect(self.slot_horizontalScrollBarChanged)
  205. #self.connect(self.ui.graphicsView.verticalScrollBar(), SIGNAL("valueChanged.connect(self.slot_verticalScrollBarChanged)
  206. #self.connect(self.scene, SIGNAL("sceneGroupMoved(int, int, QPointF)"), SLOT("slot_canvasItemMoved(int, int, QPointF)"))
  207. #self.connect(self.scene, SIGNAL("scaleChanged(double)"), SLOT("slot_canvasScaleChanged(double)"))
  208. self.DebugCallback.connect(self.slot_handleDebugCallback)
  209. self.PluginAddedCallback.connect(self.slot_handlePluginAddedCallback)
  210. self.PluginRemovedCallback.connect(self.slot_handlePluginRemovedCallback)
  211. self.PluginRenamedCallback.connect(self.slot_handlePluginRenamedCallback)
  212. self.ParameterValueChangedCallback.connect(self.slot_handleParameterValueChangedCallback)
  213. self.ParameterDefaultChangedCallback.connect(self.slot_handleParameterDefaultChangedCallback)
  214. self.ParameterMidiChannelChangedCallback.connect(self.slot_handleParameterMidiChannelChangedCallback)
  215. self.ParameterMidiCcChangedCallback.connect(self.slot_handleParameterMidiCcChangedCallback)
  216. self.ProgramChangedCallback.connect(self.slot_handleProgramChangedCallback)
  217. self.MidiProgramChangedCallback.connect(self.slot_handleMidiProgramChangedCallback)
  218. self.NoteOnCallback.connect(self.slot_handleNoteOnCallback)
  219. self.NoteOffCallback.connect(self.slot_handleNoteOffCallback)
  220. self.ShowGuiCallback.connect(self.slot_handleShowGuiCallback)
  221. self.UpdateCallback.connect(self.slot_handleUpdateCallback)
  222. self.ReloadInfoCallback.connect(self.slot_handleReloadInfoCallback)
  223. self.ReloadParametersCallback.connect(self.slot_handleReloadParametersCallback)
  224. self.ReloadProgramsCallback.connect(self.slot_handleReloadProgramsCallback)
  225. self.ReloadAllCallback.connect(self.slot_handleReloadAllCallback)
  226. self.PatchbayClientAddedCallback.connect(self.slot_handlePatchbayClientAddedCallback)
  227. self.PatchbayClientRemovedCallback.connect(self.slot_handlePatchbayClientRemovedCallback)
  228. self.PatchbayClientRenamedCallback.connect(self.slot_handlePatchbayClientRenamedCallback)
  229. self.PatchbayPortAddedCallback.connect(self.slot_handlePatchbayPortAddedCallback)
  230. self.PatchbayPortRemovedCallback.connect(self.slot_handlePatchbayPortRemovedCallback)
  231. self.PatchbayPortRenamedCallback.connect(self.slot_handlePatchbayPortRenamedCallback)
  232. self.PatchbayConnectionAddedCallback.connect(self.slot_handlePatchbayConnectionAddedCallback)
  233. self.PatchbayConnectionRemovedCallback.connect(self.slot_handlePatchbayConnectionRemovedCallback)
  234. self.PatchbayIconChangedCallback.connect(self.slot_handlePatchbayIconChangedCallback)
  235. #self.BufferSizeChangedCallback.connect(self.slot_handleBufferSizeChangedCallback)
  236. #self.SampleRateChangedCallback(double)"), SLOT("slot_handleSampleRateChangedCallback(double)"))
  237. #self.NSM_AnnounceCallback(QString)"), SLOT("slot_handleNSM_AnnounceCallback(QString)"))
  238. #self.NSM_OpenCallback(QString)"), SLOT("slot_handleNSM_OpenCallback(QString)"))
  239. #self.NSM_SaveCallback()"), SLOT("slot_handleNSM_SaveCallback()"))
  240. #self.ErrorCallback(QString)"), SLOT("slot_handleErrorCallback(QString)"))
  241. #self.QuitCallback()"), SLOT("slot_handleQuitCallback()"))
  242. self.SIGUSR1.connect(self.slot_handleSIGUSR1)
  243. self.SIGTERM.connect(self.slot_handleSIGTERM)
  244. # -----------------------------------------------------------------
  245. def init(self):
  246. self.fIdleTimerFast = self.startTimer(50)
  247. self.fIdleTimerSlow = self.startTimer(50*2)
  248. def getExtraStuff(self, plugin):
  249. ptype = plugin['type']
  250. if ptype == PLUGIN_LADSPA:
  251. uniqueId = plugin['uniqueId']
  252. self.maybeLoadRDFs()
  253. for rdfItem in self.fLadspaRdfList:
  254. if rdfItem.UniqueID == uniqueId:
  255. return pointer(rdfItem)
  256. elif ptype in (PLUGIN_GIG, PLUGIN_SF2, PLUGIN_SFZ):
  257. if plugin['name'].lower().endswith(" (16 outputs)"):
  258. # return a dummy non-null pointer
  259. INTPOINTER = POINTER(c_int)
  260. int1 = c_int(0x1)
  261. addr = addressof(int1)
  262. return cast(addr, INTPOINTER)
  263. return c_nullptr
  264. def maybeLoadRDFs(self):
  265. if not self.fLadspaRdfNeedsUpdate:
  266. return
  267. self.fLadspaRdfNeedsUpdate = False
  268. self.fLadspaRdfList = []
  269. if not haveLRDF:
  270. return
  271. settingsDir = os.path.join(HOME, ".config", "falkTX")
  272. frLadspaFile = os.path.join(settingsDir, "ladspa_rdf.db")
  273. if os.path.exists(frLadspaFile):
  274. frLadspa = open(frLadspaFile, 'r')
  275. try:
  276. self.fLadspaRdfList = ladspa_rdf.get_c_ladspa_rdfs(json.load(frLadspa))
  277. except:
  278. pass
  279. frLadspa.close()
  280. def setLoadRDFsNeeded(self):
  281. self.fLadspaRdfNeedsUpdate = True
  282. # -----------------------------------------------------------------
  283. @pyqtSlot()
  284. def slot_pluginAdd(self):
  285. dialog = PluginDatabaseW(self)
  286. if not dialog.exec_():
  287. return
  288. if not Carla.host.is_engine_running():
  289. QMessageBox.warning(self, self.tr("Warning"), self.tr("Cannot add new plugins while engine is stopped"))
  290. return
  291. btype = dialog.fRetPlugin['build']
  292. ptype = dialog.fRetPlugin['type']
  293. filename = dialog.fRetPlugin['binary']
  294. label = dialog.fRetPlugin['label']
  295. extraStuff = self.getExtraStuff(dialog.fRetPlugin)
  296. if not Carla.host.add_plugin(btype, ptype, filename, None, label, c_nullptr):
  297. CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to load plugin"), cString(Carla.host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)
  298. return
  299. @pyqtSlot()
  300. def slot_pluginRemoveAll(self):
  301. self.fContainer.removeAllPlugins()
  302. Carla.host.remove_all_plugins()
  303. @pyqtSlot()
  304. def slot_configureCarla(self):
  305. dialog = CarlaSettingsW(self, False) # TODO - hasGL
  306. if not dialog.exec_():
  307. return
  308. #self.loadSettings(False)
  309. #patchcanvas.clear()
  310. #pOptions = patchcanvas.options_t()
  311. #pOptions.theme_name = self.fSavedSettings["Canvas/Theme"]
  312. #pOptions.auto_hide_groups = self.fSavedSettings["Canvas/AutoHideGroups"]
  313. #pOptions.use_bezier_lines = self.fSavedSettings["Canvas/UseBezierLines"]
  314. #pOptions.antialiasing = self.fSavedSettings["Canvas/Antialiasing"]
  315. #pOptions.eyecandy = self.fSavedSettings["Canvas/EyeCandy"]
  316. #pFeatures = patchcanvas.features_t()
  317. #pFeatures.group_info = False
  318. #pFeatures.group_rename = False
  319. #pFeatures.port_info = False
  320. #pFeatures.port_rename = False
  321. #pFeatures.handle_group_pos = True
  322. #patchcanvas.setOptions(pOptions)
  323. #patchcanvas.setFeatures(pFeatures)
  324. #patchcanvas.init("Carla", self.scene, canvasCallback, False)
  325. #if self.fEngineStarted:
  326. #Carla.host.patchbay_refresh()
  327. @pyqtSlot()
  328. def slot_aboutCarla(self):
  329. CarlaAboutW(self).exec_()
  330. @pyqtSlot()
  331. def slot_aboutQt(self):
  332. QApplication.instance().aboutQt()
  333. # -----------------------------------------------------------------
  334. @pyqtSlot(int, int, int, float, str)
  335. def slot_handleDebugCallback(self, pluginId, value1, value2, value3, valueStr):
  336. print("DEBUG:", pluginId, value1, value2, value3, valueStr)
  337. #self.ui.pte_log.appendPlainText(valueStr.replace("", "DEBUG: ").replace("", "ERROR: ").replace("", "").replace("\n", ""))
  338. @pyqtSlot(int)
  339. def slot_handlePluginAddedCallback(self, pluginId):
  340. self.fContainer.addPlugin(pluginId, self.fIsProjectLoading)
  341. if self.fContainer.getPluginCount() == 1:
  342. self.ui.act_plugin_remove_all.setEnabled(True)
  343. @pyqtSlot(int)
  344. def slot_handlePluginRemovedCallback(self, pluginId):
  345. self.fContainer.removePlugin(pluginId)
  346. if self.fContainer.getPluginCount() == 0:
  347. self.ui.act_plugin_remove_all.setEnabled(False)
  348. @pyqtSlot(int, str)
  349. def slot_handlePluginRenamedCallback(self, pluginId, newName):
  350. self.fContainer.renamePlugin(pluginId, newName)
  351. @pyqtSlot(int, int, float)
  352. def slot_handleParameterValueChangedCallback(self, pluginId, parameterId, value):
  353. self.fContainer.setParameterValue(parameterId, value)
  354. @pyqtSlot(int, int, float)
  355. def slot_handleParameterDefaultChangedCallback(self, pluginId, parameterId, value):
  356. self.fContainer.setParameterDefault(parameterId, value)
  357. @pyqtSlot(int, int, int)
  358. def slot_handleParameterMidiChannelChangedCallback(self, pluginId, parameterId, channel):
  359. self.fContainer.setParameterMidiChannel(parameterId, channel)
  360. @pyqtSlot(int, int, int)
  361. def slot_handleParameterMidiCcChangedCallback(self, pluginId, parameterId, cc):
  362. self.fContainer.setParameterMidiCC(parameterId, cc)
  363. @pyqtSlot(int, int)
  364. def slot_handleProgramChangedCallback(self, pluginId, programId):
  365. self.fContainer.setProgram(programId)
  366. @pyqtSlot(int, int)
  367. def slot_handleMidiProgramChangedCallback(self, pluginId, midiProgramId):
  368. self.fContainer.setMidiProgram(midiProgramId)
  369. @pyqtSlot(int, int, int, int)
  370. def slot_handleNoteOnCallback(self, pluginId, channel, note, velo):
  371. self.fContainer.noteOn(channel, note)
  372. @pyqtSlot(int, int, int)
  373. def slot_handleNoteOffCallback(self, pluginId, channel, note):
  374. self.fContainer.noteOff(channel, note)
  375. @pyqtSlot(int, int)
  376. def slot_handleShowGuiCallback(self, pluginId, state):
  377. self.fContainer.setGuiState(pluginId, state)
  378. @pyqtSlot(int)
  379. def slot_handleUpdateCallback(self, pluginId):
  380. self.fContainer.updateInfo(pluginId)
  381. @pyqtSlot(int)
  382. def slot_handleReloadInfoCallback(self, pluginId):
  383. self.fContainer.reloadInfo(pluginId)
  384. @pyqtSlot(int)
  385. def slot_handleReloadParametersCallback(self, pluginId):
  386. self.fContainer.reloadParameters(pluginId)
  387. @pyqtSlot(int)
  388. def slot_handleReloadProgramsCallback(self, pluginId):
  389. self.fContainer.reloadPrograms(pluginId)
  390. @pyqtSlot(int)
  391. def slot_handleReloadAllCallback(self, pluginId):
  392. self.fContainer.reloadAll(pluginId)
  393. @pyqtSlot(int, int, str)
  394. def slot_handlePatchbayClientAddedCallback(self, clientId, clientIcon, clientName):
  395. self.fContainer.patchbayClientAdded(clientId, clientIcon, clientName)
  396. @pyqtSlot(int, str)
  397. def slot_handlePatchbayClientRemovedCallback(self, clientId, clientName):
  398. self.fContainer.patchbayClientRemoved(clientId, clientName)
  399. @pyqtSlot(int, str)
  400. def slot_handlePatchbayClientRenamedCallback(self, clientId, newClientName):
  401. self.fContainer.patchbayClientRenamed(clientId, newClientName)
  402. @pyqtSlot(int, int, int, str)
  403. def slot_handlePatchbayPortAddedCallback(self, clientId, portId, portFlags, portName):
  404. self.fContainer.patchbayPortAdded(clientId, portId, portFlags, portName)
  405. @pyqtSlot(int, int, str)
  406. def slot_handlePatchbayPortRemovedCallback(self, groupId, portId, fullPortName):
  407. self.fContainer.patchbayPortRemoved(groupId, portId, fullPortName)
  408. @pyqtSlot(int, int, str)
  409. def slot_handlePatchbayPortRenamedCallback(self, groupId, portId, newPortName):
  410. self.fContainer.patchbayPortRenamed(groupId, portId, newPortName)
  411. @pyqtSlot(int, int, int)
  412. def slot_handlePatchbayConnectionAddedCallback(self, connectionId, portOutId, portInId):
  413. self.fContainer.patchbayConnectionAdded(connectionId, portOutId, portInId)
  414. @pyqtSlot(int)
  415. def slot_handlePatchbayConnectionRemovedCallback(self, connectionId):
  416. self.fContainer.patchbayConnectionRemoved(connectionId)
  417. @pyqtSlot(int, int)
  418. def slot_handlePatchbayIconChangedCallback(self, clientId, clientIcon):
  419. self.fContainer.patchbayIconChanged(clientId, clientIcon)
  420. # -----------------------------------------------------------------
  421. @pyqtSlot()
  422. def slot_handleSIGUSR1(self):
  423. print("Got SIGUSR1 -> Saving project now")
  424. #QTimer.singleShot(0, self, SLOT("slot_fileSave()"))
  425. @pyqtSlot()
  426. def slot_handleSIGTERM(self):
  427. print("Got SIGTERM -> Closing now")
  428. self.close()
  429. # -----------------------------------------------------------------
  430. def timerEvent(self, event):
  431. if event.timerId() == self.fIdleTimerFast:
  432. Carla.host.engine_idle()
  433. self.fContainer.idleFast()
  434. elif event.timerId() == self.fIdleTimerSlow:
  435. self.fContainer.idleSlow()
  436. QMainWindow.timerEvent(self, event)
  437. def closeEvent(self, event):
  438. if self.fIdleTimerFast != 0:
  439. self.killTimer(self.fIdleTimerFast)
  440. self.fIdleTimerFast = 0
  441. if self.fIdleTimerSlow != 0:
  442. self.killTimer(self.fIdleTimerSlow)
  443. self.fIdleTimerSlow = 0
  444. QMainWindow.closeEvent(self, event)
  445. # ------------------------------------------------------------------------------------------------------------
  446. # Engine callback
  447. def EngineCallback(ptr, action, pluginId, value1, value2, value3, valueStr):
  448. if pluginId < 0 or not Carla.gui:
  449. return
  450. if action == CALLBACK_DEBUG:
  451. Carla.gui.DebugCallback.emit(pluginId, value1, value2, value3, cString(valueStr))
  452. elif action == CALLBACK_PLUGIN_ADDED:
  453. Carla.gui.PluginAddedCallback.emit(pluginId)
  454. elif action == CALLBACK_PLUGIN_REMOVED:
  455. Carla.gui.PluginRemovedCallback.emit(pluginId)
  456. elif action == CALLBACK_PLUGIN_RENAMED:
  457. Carla.gui.PluginRenamedCallback.emit(pluginId, valueStr)
  458. elif action == CALLBACK_PARAMETER_VALUE_CHANGED:
  459. Carla.gui.ParameterValueChangedCallback.emit(pluginId, value1, value3)
  460. elif action == CALLBACK_PARAMETER_DEFAULT_CHANGED:
  461. Carla.gui.ParameterDefaultChangedCallback.emit(pluginId, value1, value3)
  462. elif action == CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED:
  463. Carla.gui.ParameterMidiChannelChangedCallback.emit(pluginId, value1, value2)
  464. elif action == CALLBACK_PARAMETER_MIDI_CC_CHANGED:
  465. Carla.gui.ParameterMidiCcChangedCallback.emit(pluginId, value1, value2)
  466. elif action == CALLBACK_PROGRAM_CHANGED:
  467. Carla.gui.ProgramChangedCallback.emit(pluginId, value1)
  468. elif action == CALLBACK_MIDI_PROGRAM_CHANGED:
  469. Carla.gui.MidiProgramChangedCallback.emit(pluginId, value1)
  470. elif action == CALLBACK_NOTE_ON:
  471. Carla.gui.NoteOnCallback.emit(pluginId, value1, value2, value3)
  472. elif action == CALLBACK_NOTE_OFF:
  473. Carla.gui.NoteOffCallback.emit(pluginId, value1, value2)
  474. elif action == CALLBACK_SHOW_GUI:
  475. Carla.gui.ShowGuiCallback.emit(pluginId, value1)
  476. elif action == CALLBACK_UPDATE:
  477. Carla.gui.UpdateCallback.emit(pluginId)
  478. elif action == CALLBACK_RELOAD_INFO:
  479. Carla.gui.ReloadInfoCallback.emit(pluginId)
  480. elif action == CALLBACK_RELOAD_PARAMETERS:
  481. Carla.gui.ReloadParametersCallback.emit(pluginId)
  482. elif action == CALLBACK_RELOAD_PROGRAMS:
  483. Carla.gui.ReloadProgramsCallback.emit(pluginId)
  484. elif action == CALLBACK_RELOAD_ALL:
  485. Carla.gui.ReloadAllCallback.emit(pluginId)
  486. elif action == CALLBACK_PATCHBAY_CLIENT_ADDED:
  487. Carla.gui.PatchbayClientAddedCallback.emit(value1, value2, cString(valueStr))
  488. elif action == CALLBACK_PATCHBAY_CLIENT_REMOVED:
  489. Carla.gui.PatchbayClientRemovedCallback.emit(value1, cString(valueStr))
  490. elif action == CALLBACK_PATCHBAY_CLIENT_RENAMED:
  491. Carla.gui.PatchbayClientRenamedCallback.emit(value1, cString(valueStr))
  492. elif action == CALLBACK_PATCHBAY_PORT_ADDED:
  493. Carla.gui.PatchbayPortAddedCallback.emit(value1, value2, int(value3), cString(valueStr))
  494. elif action == CALLBACK_PATCHBAY_PORT_REMOVED:
  495. Carla.gui.PatchbayPortRemovedCallback.emit(value1, value2, cString(valueStr))
  496. elif action == CALLBACK_PATCHBAY_PORT_RENAMED:
  497. Carla.gui.PatchbayPortRenamedCallback.emit(value1, value2, cString(valueStr))
  498. elif action == CALLBACK_PATCHBAY_CONNECTION_ADDED:
  499. Carla.gui.PatchbayConnectionAddedCallback.emit(value1, value2, value3)
  500. elif action == CALLBACK_PATCHBAY_CONNECTION_REMOVED:
  501. Carla.gui.PatchbayConnectionRemovedCallback.emit(value1)
  502. elif action == CALLBACK_PATCHBAY_ICON_CHANGED:
  503. Carla.gui.PatchbayIconChangedCallback.emit(value1, value2)
  504. elif action == CALLBACK_BUFFER_SIZE_CHANGED:
  505. Carla.gui.BufferSizeChangedCallback.emit(value1)
  506. elif action == CALLBACK_SAMPLE_RATE_CHANGED:
  507. Carla.gui.SampleRateChangedCallback.emit(value3)
  508. elif action == CALLBACK_NSM_ANNOUNCE:
  509. Carla.gui.NSM_AnnounceCallback.emit(cString(valueStr))
  510. elif action == CALLBACK_NSM_OPEN:
  511. Carla.gui.NSM_OpenCallback.emit(cString(valueStr))
  512. elif action == CALLBACK_NSM_SAVE:
  513. Carla.gui.NSM_SaveCallback.emit()
  514. elif action == CALLBACK_ERROR:
  515. Carla.gui.ErrorCallback.emit(cString(valueStr))
  516. elif action == CALLBACK_QUIT:
  517. Carla.gui.QuitCallback.emit()