diff --git a/Makefile b/Makefile index 95ab7dcbe..ee9fc4b8b 100644 --- a/Makefile +++ b/Makefile @@ -87,6 +87,7 @@ UIs = \ source/ui_carla_about.py \ source/ui_carla_database.py \ source/ui_carla_edit.py \ + source/ui_carla_host.py \ source/ui_carla_parameter.py \ source/ui_carla_plugin.py \ source/ui_carla_refresh.py \ diff --git a/source/carla-mini b/source/carla-mini index 0a324185c..0f1631026 100755 --- a/source/carla-mini +++ b/source/carla-mini @@ -31,6 +31,7 @@ except: from carla_host import * from carla_rack import CarlaRackW +#from carla_patchbay import CarlaPatchbayW # ------------------------------------------------------------------------------------------------------------ # Main Window @@ -38,40 +39,21 @@ from carla_rack import CarlaRackW class CarlaMiniW(HostWindow): def __init__(self, parent=None): HostWindow.__init__(self, parent) - #self.ui = ui_carla.Ui_CarlaMainW() - #self.ui.setupUi(self) - - Carla.host.engine_init("JACK", "Carla") self.fContainer = CarlaRackW(self) + #self.fContainer = CarlaPatchbayW(self) self.setCentralWidget(self.fContainer) + Carla.host.engine_init("JACK", "Carla") + self.init() - QTimer.singleShot(0, self.slot_pluginAdd) + Carla.host.patchbay_refresh() def closeEvent(self, event): Carla.host.engine_close() HostWindow.closeEvent(self, event) - @pyqtSlot() - def slot_pluginAdd(self): - dialog = PluginDatabaseW(self) - - if not dialog.exec_(): - return - - btype = dialog.fRetPlugin['build'] - ptype = dialog.fRetPlugin['type'] - filename = dialog.fRetPlugin['binary'] - label = dialog.fRetPlugin['label'] - - if not Carla.host.add_plugin(btype, ptype, filename, None, label, c_nullptr): - CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to load plugin"), cString(Carla.host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok) - return - - self.fContainer.addPlugin(0) - # ------------------------------------------------------------------------------------------------------------ # --------------- main ------------------ @@ -96,6 +78,8 @@ if __name__ == '__main__': # Create GUI and start engine Carla.gui = CarlaMiniW() + Carla.host.patchbay_refresh() + # Show GUI Carla.gui.show() diff --git a/source/carla.py b/source/carla.py index 50c7b2d99..9f579c27c 100755 --- a/source/carla.py +++ b/source/carla.py @@ -32,15 +32,6 @@ import ui_carla from carla_shared import * -# ------------------------------------------------------------------------------------------------------------ -# Try Import OpenGL - -try: - from PyQt4.QtOpenGL import QGLWidget - hasGL = True -except: - hasGL = False - # ------------------------------------------------------------------------------------------------------------ # Static Variables diff --git a/source/carla_host.py b/source/carla_host.py index c4a18e9c1..d3f3d31b2 100644 --- a/source/carla_host.py +++ b/source/carla_host.py @@ -20,13 +20,15 @@ # Imports (Global) try: - from PyQt5.QtWidgets import QMainWindow + from PyQt5.QtWidgets import QApplication, QMainWindow except: - from PyQt4.QtGui import QMainWindow + from PyQt4.QtGui import QApplication, QMainWindow # ------------------------------------------------------------------------------------------------------------ # Imports (Custom) +import ui_carla_host + from carla_database import * from carla_settings import * from carla_widgets import * @@ -38,15 +40,111 @@ class CarlaDummyW(object): def __init__(self, parent): object.__init__(self) - def addPlugin(self, pluginId): + # ----------------------------------------------------------------- + + def getPluginCount(self): + return 0 + + def getPlugin(self, pluginId): + return None + + # ----------------------------------------------------------------- + + def addPlugin(self, pluginId, isProjectLoading): pass def removePlugin(self, pluginId): pass + def renamePlugin(self, pluginId, newName): + pass + def removeAllPlugins(self): pass + # ----------------------------------------------------------------- + + def setParameterValue(self, pluginId, index, value): + pass + + def setParameterDefault(self, pluginId, index, value): + pass + + def setParameterMidiChannel(self, pluginId, index, channel): + pass + + def setParameterMidiCC(self, pluginId, index, cc): + pass + + # ----------------------------------------------------------------- + + def setProgram(self, pluginId, index): + pass + + def setMidiProgram(self, pluginId, index): + pass + + # ----------------------------------------------------------------- + + def noteOn(self, pluginId, channel, note, velocity): + pass + + def noteOff(self, pluginId, channel, note): + pass + + # ----------------------------------------------------------------- + + def setGuiState(self, pluginId, state): + pass + + # ----------------------------------------------------------------- + + def updateInfo(self, pluginId): + pass + + def reloadInfo(self, pluginId): + pass + + def reloadParameters(self, pluginId): + pass + + def reloadPrograms(self, pluginId): + pass + + def reloadAll(self, pluginId): + pass + + # ----------------------------------------------------------------- + + def patchbayClientAdded(self, clientId, clientIcon, clientName): + pass + + def patchbayClientRemoved(self, clientId, clientName): + pass + + def patchbayClientRenamed(self, clientId, newClientName): + pass + + def patchbayPortAdded(self, clientId, portId, portFlags, portName): + pass + + def patchbayPortRemoved(self, groupId, portId, fullPortName): + pass + + def patchbayPortRenamed(self, groupId, portId, newPortName): + pass + + def patchbayConnectionAdded(self, connectionId, portOutId, portInId): + pass + + def patchbayConnectionRemoved(self, connectionId): + pass + + def patchbayIconChanged(self, clientId, clientIcon): + pass + + # ----------------------------------------------------------------- + def idleFast(self): pass @@ -97,8 +195,8 @@ class HostWindow(QMainWindow): def __init__(self, parent): QMainWindow.__init__(self, parent) - #self.ui = ui_carla_plugin.Ui_PluginWidget() - #self.ui.setupUi(self) + self.ui = ui_carla_host.Ui_CarlaHostW() + self.ui.setupUi(self) # ------------------------------------------------------------- # Set bridge paths @@ -169,6 +267,7 @@ class HostWindow(QMainWindow): self.fIdleTimerFast = 0 self.fIdleTimerSlow = 0 + self.fIsProjectLoading = False self.fLadspaRdfNeedsUpdate = True self.fLadspaRdfList = [] @@ -176,6 +275,107 @@ class HostWindow(QMainWindow): self.fContainer = CarlaDummyW(self) # ------------------------------------------------------------- + # Connect actions to functions + + #self.connect(self.ui.act_file_new, SIGNAL("triggered()"), SLOT("slot_fileNew()")) + #self.connect(self.ui.act_file_open, SIGNAL("triggered()"), SLOT("slot_fileOpen()")) + #self.connect(self.ui.act_file_save, SIGNAL("triggered()"), SLOT("slot_fileSave()")) + #self.connect(self.ui.act_file_save_as, SIGNAL("triggered()"), SLOT("slot_fileSaveAs()")) + ##self.connect(self.ui.act_file_export_lv2, SIGNAL("triggered()"), SLOT("slot_fileExportLv2Preset()")) + + #self.connect(self.ui.act_engine_start, SIGNAL("triggered()"), SLOT("slot_engineStart()")) + #self.connect(self.ui.act_engine_stop, SIGNAL("triggered()"), SLOT("slot_engineStop()")) + + self.ui.act_plugin_add.triggered.connect(self.slot_pluginAdd) + self.ui.act_plugin_add2.triggered.connect(self.slot_pluginAdd) + self.ui.act_plugin_remove_all.triggered.connect(self.slot_pluginRemoveAll) + + #self.connect(self.ui.act_plugins_enable, SIGNAL("triggered()"), SLOT("slot_pluginsEnable()")) + #self.connect(self.ui.act_plugins_disable, SIGNAL("triggered()"), SLOT("slot_pluginsDisable()")) + #self.connect(self.ui.act_plugins_panic, SIGNAL("triggered()"), SLOT("slot_pluginsDisable()")) + #self.connect(self.ui.act_plugins_volume100, SIGNAL("triggered()"), SLOT("slot_pluginsVolume100()")) + #self.connect(self.ui.act_plugins_mute, SIGNAL("triggered()"), SLOT("slot_pluginsMute()")) + #self.connect(self.ui.act_plugins_wet100, SIGNAL("triggered()"), SLOT("slot_pluginsWet100()")) + #self.connect(self.ui.act_plugins_bypass, SIGNAL("triggered()"), SLOT("slot_pluginsBypass()")) + #self.connect(self.ui.act_plugins_center, SIGNAL("triggered()"), SLOT("slot_pluginsCenter()")) + + #self.connect(self.ui.act_transport_play, SIGNAL("triggered(bool)"), SLOT("slot_transportPlayPause(bool)")) + #self.connect(self.ui.act_transport_stop, SIGNAL("triggered()"), SLOT("slot_transportStop()")) + #self.connect(self.ui.act_transport_backwards, SIGNAL("triggered()"), SLOT("slot_transportBackwards()")) + #self.connect(self.ui.act_transport_forwards, SIGNAL("triggered()"), SLOT("slot_transportForwards()")) + + #self.ui.act_canvas_arrange.setEnabled(False) # TODO, later + #self.connect(self.ui.act_canvas_arrange, SIGNAL("triggered()"), SLOT("slot_canvasArrange()")) + #self.connect(self.ui.act_canvas_refresh, SIGNAL("triggered()"), SLOT("slot_canvasRefresh()")) + #self.connect(self.ui.act_canvas_zoom_fit, SIGNAL("triggered()"), SLOT("slot_canvasZoomFit()")) + #self.connect(self.ui.act_canvas_zoom_in, SIGNAL("triggered()"), SLOT("slot_canvasZoomIn()")) + #self.connect(self.ui.act_canvas_zoom_out, SIGNAL("triggered()"), SLOT("slot_canvasZoomOut()")) + #self.connect(self.ui.act_canvas_zoom_100, SIGNAL("triggered()"), SLOT("slot_canvasZoomReset()")) + #self.connect(self.ui.act_canvas_print, SIGNAL("triggered()"), SLOT("slot_canvasPrint()")) + #self.connect(self.ui.act_canvas_save_image, SIGNAL("triggered()"), SLOT("slot_canvasSaveImage()")) + + self.ui.act_settings_configure.triggered.connect(self.slot_configureCarla) + + self.ui.act_help_about.triggered.connect(self.slot_aboutCarla) + self.ui.act_help_about_qt.triggered.connect(self.slot_aboutQt) + + #self.connect(self.ui.splitter, SIGNAL("splitterMoved.connect(self.slot_splitterMoved()")) + + #self.connect(self.ui.cb_disk, SIGNAL("currentIndexChanged.connect(self.slot_diskFolderChanged) + #self.connect(self.ui.b_disk_add, SIGNAL("clicked()"), SLOT("slot_diskFolderAdd()")) + #self.connect(self.ui.b_disk_remove, SIGNAL("clicked()"), SLOT("slot_diskFolderRemove()")) + #self.connect(self.ui.fileTreeView, SIGNAL("doubleClicked(QModelIndex)"), SLOT("slot_fileTreeDoubleClicked(QModelIndex)")) + #self.connect(self.ui.miniCanvasPreview, SIGNAL("miniCanvasMoved(double, double)"), SLOT("slot_miniCanvasMoved(double, double)")) + + #self.connect(self.ui.graphicsView.horizontalScrollBar(), SIGNAL("valueChanged.connect(self.slot_horizontalScrollBarChanged) + #self.connect(self.ui.graphicsView.verticalScrollBar(), SIGNAL("valueChanged.connect(self.slot_verticalScrollBarChanged) + + #self.connect(self.scene, SIGNAL("sceneGroupMoved(int, int, QPointF)"), SLOT("slot_canvasItemMoved(int, int, QPointF)")) + #self.connect(self.scene, SIGNAL("scaleChanged(double)"), SLOT("slot_canvasScaleChanged(double)")) + + self.DebugCallback.connect(self.slot_handleDebugCallback) + self.PluginAddedCallback.connect(self.slot_handlePluginAddedCallback) + self.PluginRemovedCallback.connect(self.slot_handlePluginRemovedCallback) + self.PluginRenamedCallback.connect(self.slot_handlePluginRenamedCallback) + self.ParameterValueChangedCallback.connect(self.slot_handleParameterValueChangedCallback) + self.ParameterDefaultChangedCallback.connect(self.slot_handleParameterDefaultChangedCallback) + self.ParameterMidiChannelChangedCallback.connect(self.slot_handleParameterMidiChannelChangedCallback) + self.ParameterMidiCcChangedCallback.connect(self.slot_handleParameterMidiCcChangedCallback) + self.ProgramChangedCallback.connect(self.slot_handleProgramChangedCallback) + self.MidiProgramChangedCallback.connect(self.slot_handleMidiProgramChangedCallback) + self.NoteOnCallback.connect(self.slot_handleNoteOnCallback) + self.NoteOffCallback.connect(self.slot_handleNoteOffCallback) + self.ShowGuiCallback.connect(self.slot_handleShowGuiCallback) + self.UpdateCallback.connect(self.slot_handleUpdateCallback) + self.ReloadInfoCallback.connect(self.slot_handleReloadInfoCallback) + self.ReloadParametersCallback.connect(self.slot_handleReloadParametersCallback) + self.ReloadProgramsCallback.connect(self.slot_handleReloadProgramsCallback) + self.ReloadAllCallback.connect(self.slot_handleReloadAllCallback) + self.PatchbayClientAddedCallback.connect(self.slot_handlePatchbayClientAddedCallback) + self.PatchbayClientRemovedCallback.connect(self.slot_handlePatchbayClientRemovedCallback) + self.PatchbayClientRenamedCallback.connect(self.slot_handlePatchbayClientRenamedCallback) + self.PatchbayPortAddedCallback.connect(self.slot_handlePatchbayPortAddedCallback) + self.PatchbayPortRemovedCallback.connect(self.slot_handlePatchbayPortRemovedCallback) + self.PatchbayPortRenamedCallback.connect(self.slot_handlePatchbayPortRenamedCallback) + self.PatchbayConnectionAddedCallback.connect(self.slot_handlePatchbayConnectionAddedCallback) + self.PatchbayConnectionRemovedCallback.connect(self.slot_handlePatchbayConnectionRemovedCallback) + self.PatchbayIconChangedCallback.connect(self.slot_handlePatchbayIconChangedCallback) + #self.BufferSizeChangedCallback.connect(self.slot_handleBufferSizeChangedCallback) + #self.SampleRateChangedCallback(double)"), SLOT("slot_handleSampleRateChangedCallback(double)")) + #self.NSM_AnnounceCallback(QString)"), SLOT("slot_handleNSM_AnnounceCallback(QString)")) + #self.NSM_OpenCallback(QString)"), SLOT("slot_handleNSM_OpenCallback(QString)")) + #self.NSM_SaveCallback()"), SLOT("slot_handleNSM_SaveCallback()")) + #self.ErrorCallback(QString)"), SLOT("slot_handleErrorCallback(QString)")) + #self.QuitCallback()"), SLOT("slot_handleQuitCallback()")) + + self.SIGUSR1.connect(self.slot_handleSIGUSR1) + self.SIGTERM.connect(self.slot_handleSIGTERM) + + # ----------------------------------------------------------------- + + def init(self): + self.fIdleTimerFast = self.startTimer(50) + self.fIdleTimerSlow = self.startTimer(50*2) def getExtraStuff(self, plugin): ptype = plugin['type'] @@ -225,9 +425,204 @@ class HostWindow(QMainWindow): def setLoadRDFsNeeded(self): self.fLadspaRdfNeedsUpdate = True - def init(self): - self.fIdleTimerFast = self.startTimer(50) - self.fIdleTimerSlow = self.startTimer(50*2) + # ----------------------------------------------------------------- + + @pyqtSlot() + def slot_pluginAdd(self): + dialog = PluginDatabaseW(self) + + if not dialog.exec_(): + return + + if not Carla.host.is_engine_running(): + QMessageBox.warning(self, self.tr("Warning"), self.tr("Cannot add new plugins while engine is stopped")) + return + + btype = dialog.fRetPlugin['build'] + ptype = dialog.fRetPlugin['type'] + filename = dialog.fRetPlugin['binary'] + label = dialog.fRetPlugin['label'] + extraStuff = self.getExtraStuff(dialog.fRetPlugin) + + if not Carla.host.add_plugin(btype, ptype, filename, None, label, c_nullptr): + CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to load plugin"), cString(Carla.host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok) + return + + @pyqtSlot() + def slot_pluginRemoveAll(self): + self.fContainer.removeAllPlugins() + + Carla.host.remove_all_plugins() + + @pyqtSlot() + def slot_configureCarla(self): + dialog = CarlaSettingsW(self, False) # TODO - hasGL + + if not dialog.exec_(): + return + + #self.loadSettings(False) + #patchcanvas.clear() + + #pOptions = patchcanvas.options_t() + #pOptions.theme_name = self.fSavedSettings["Canvas/Theme"] + #pOptions.auto_hide_groups = self.fSavedSettings["Canvas/AutoHideGroups"] + #pOptions.use_bezier_lines = self.fSavedSettings["Canvas/UseBezierLines"] + #pOptions.antialiasing = self.fSavedSettings["Canvas/Antialiasing"] + #pOptions.eyecandy = self.fSavedSettings["Canvas/EyeCandy"] + + #pFeatures = patchcanvas.features_t() + #pFeatures.group_info = False + #pFeatures.group_rename = False + #pFeatures.port_info = False + #pFeatures.port_rename = False + #pFeatures.handle_group_pos = True + + #patchcanvas.setOptions(pOptions) + #patchcanvas.setFeatures(pFeatures) + #patchcanvas.init("Carla", self.scene, canvasCallback, False) + + #if self.fEngineStarted: + #Carla.host.patchbay_refresh() + + @pyqtSlot() + def slot_aboutCarla(self): + CarlaAboutW(self).exec_() + + @pyqtSlot() + def slot_aboutQt(self): + QApplication.instance().aboutQt() + + # ----------------------------------------------------------------- + + @pyqtSlot(int, int, int, float, str) + def slot_handleDebugCallback(self, pluginId, value1, value2, value3, valueStr): + print("DEBUG:", pluginId, value1, value2, value3, valueStr) + #self.ui.pte_log.appendPlainText(valueStr.replace("", "DEBUG: ").replace("", "ERROR: ").replace("", "").replace("\n", "")) + + @pyqtSlot(int) + def slot_handlePluginAddedCallback(self, pluginId): + self.fContainer.addPlugin(pluginId, self.fIsProjectLoading) + + if self.fContainer.getPluginCount() == 1: + self.ui.act_plugin_remove_all.setEnabled(True) + + @pyqtSlot(int) + def slot_handlePluginRemovedCallback(self, pluginId): + self.fContainer.removePlugin(pluginId) + + if self.fContainer.getPluginCount() == 0: + self.ui.act_plugin_remove_all.setEnabled(False) + + @pyqtSlot(int, str) + def slot_handlePluginRenamedCallback(self, pluginId, newName): + self.fContainer.renamePlugin(pluginId, newName) + + @pyqtSlot(int, int, float) + def slot_handleParameterValueChangedCallback(self, pluginId, parameterId, value): + self.fContainer.setParameterValue(parameterId, value) + + @pyqtSlot(int, int, float) + def slot_handleParameterDefaultChangedCallback(self, pluginId, parameterId, value): + self.fContainer.setParameterDefault(parameterId, value) + + @pyqtSlot(int, int, int) + def slot_handleParameterMidiChannelChangedCallback(self, pluginId, parameterId, channel): + self.fContainer.setParameterMidiChannel(parameterId, channel) + + @pyqtSlot(int, int, int) + def slot_handleParameterMidiCcChangedCallback(self, pluginId, parameterId, cc): + self.fContainer.setParameterMidiCC(parameterId, cc) + + @pyqtSlot(int, int) + def slot_handleProgramChangedCallback(self, pluginId, programId): + self.fContainer.setProgram(programId) + + @pyqtSlot(int, int) + def slot_handleMidiProgramChangedCallback(self, pluginId, midiProgramId): + self.fContainer.setMidiProgram(midiProgramId) + + @pyqtSlot(int, int, int, int) + def slot_handleNoteOnCallback(self, pluginId, channel, note, velo): + self.fContainer.noteOn(channel, note) + + @pyqtSlot(int, int, int) + def slot_handleNoteOffCallback(self, pluginId, channel, note): + self.fContainer.noteOff(channel, note) + + @pyqtSlot(int, int) + def slot_handleShowGuiCallback(self, pluginId, state): + self.fContainer.setGuiState(pluginId, state) + + @pyqtSlot(int) + def slot_handleUpdateCallback(self, pluginId): + self.fContainer.updateInfo(pluginId) + + @pyqtSlot(int) + def slot_handleReloadInfoCallback(self, pluginId): + self.fContainer.reloadInfo(pluginId) + + @pyqtSlot(int) + def slot_handleReloadParametersCallback(self, pluginId): + self.fContainer.reloadParameters(pluginId) + + @pyqtSlot(int) + def slot_handleReloadProgramsCallback(self, pluginId): + self.fContainer.reloadPrograms(pluginId) + + @pyqtSlot(int) + def slot_handleReloadAllCallback(self, pluginId): + self.fContainer.reloadAll(pluginId) + + @pyqtSlot(int, int, str) + def slot_handlePatchbayClientAddedCallback(self, clientId, clientIcon, clientName): + self.fContainer.patchbayClientAdded(clientId, clientIcon, clientName) + + @pyqtSlot(int, str) + def slot_handlePatchbayClientRemovedCallback(self, clientId, clientName): + self.fContainer.patchbayClientRemoved(clientId, clientName) + + @pyqtSlot(int, str) + def slot_handlePatchbayClientRenamedCallback(self, clientId, newClientName): + self.fContainer.patchbayClientRenamed(clientId, newClientName) + + @pyqtSlot(int, int, int, str) + def slot_handlePatchbayPortAddedCallback(self, clientId, portId, portFlags, portName): + self.fContainer.patchbayPortAdded(clientId, portId, portFlags, portName) + + @pyqtSlot(int, int, str) + def slot_handlePatchbayPortRemovedCallback(self, groupId, portId, fullPortName): + self.fContainer.patchbayPortRemoved(groupId, portId, fullPortName) + + @pyqtSlot(int, int, str) + def slot_handlePatchbayPortRenamedCallback(self, groupId, portId, newPortName): + self.fContainer.patchbayPortRenamed(groupId, portId, newPortName) + + @pyqtSlot(int, int, int) + def slot_handlePatchbayConnectionAddedCallback(self, connectionId, portOutId, portInId): + self.fContainer.patchbayConnectionAdded(connectionId, portOutId, portInId) + + @pyqtSlot(int) + def slot_handlePatchbayConnectionRemovedCallback(self, connectionId): + self.fContainer.patchbayConnectionRemoved(connectionId) + + @pyqtSlot(int, int) + def slot_handlePatchbayIconChangedCallback(self, clientId, clientIcon): + self.fContainer.patchbayIconChanged(clientId, clientIcon) + + # ----------------------------------------------------------------- + + @pyqtSlot() + def slot_handleSIGUSR1(self): + print("Got SIGUSR1 -> Saving project now") + #QTimer.singleShot(0, self, SLOT("slot_fileSave()")) + + @pyqtSlot() + def slot_handleSIGTERM(self): + print("Got SIGTERM -> Closing now") + self.close() + + # ----------------------------------------------------------------- def timerEvent(self, event): if event.timerId() == self.fIdleTimerFast: diff --git a/source/carla_patchbay.py b/source/carla_patchbay.py index 8574ed8b5..87d42b168 100644 --- a/source/carla_patchbay.py +++ b/source/carla_patchbay.py @@ -19,6 +19,11 @@ # ------------------------------------------------------------------------------------------------------------ # Imports (Global) +try: + from PyQt5.QtWidgets import QGraphicsView +except: + from PyQt4.QtGui import QGraphicsView + # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) @@ -26,29 +31,47 @@ import patchcanvas from carla_widgets import * +# ------------------------------------------------------------------------------------------------------------ +# Try Import OpenGL + +try: + #try: + from PyQt5.QtOpenGL import QGLWidget + #except: + #from PyQt4.QtOpenGL import QGLWidget + hasGL = True +except: + hasGL = False + # ------------------------------------------------------------------------------------------------ # Patchbay widget -class CarlaPatchbayW(QWidget): +class CarlaPatchbayW(QGraphicsView): def __init__(self, parent): - QWidget.__init__(self, parent) + QGraphicsView.__init__(self, parent) + + # ------------------------------------------------------------- + # Internal stuff + + self.fPluginCount = 0 + self.fPluginList = [] # ------------------------------------------------------------- # Set-up Canvas - self.scene = patchcanvas.PatchScene(self, self.ui.graphicsView) - self.ui.graphicsView.setScene(self.scene) - self.ui.graphicsView.setRenderHint(QPainter.Antialiasing, bool(self.fSavedSettings["Canvas/Antialiasing"] == patchcanvas.ANTIALIASING_FULL)) - if self.fSavedSettings["Canvas/UseOpenGL"] and hasGL: - self.ui.graphicsView.setViewport(QGLWidget(self.ui.graphicsView)) - self.ui.graphicsView.setRenderHint(QPainter.HighQualityAntialiasing, self.fSavedSettings["Canvas/HighQualityAntialiasing"]) + self.scene = patchcanvas.PatchScene(self, self) # FIXME? + self.setScene(self.scene) + #self.setRenderHint(QPainter.Antialiasing, bool(self.fSavedSettings["Canvas/Antialiasing"] == patchcanvas.ANTIALIASING_FULL)) + #if self.fSavedSettings["Canvas/UseOpenGL"] and hasGL: + #self.setViewport(QGLWidget(self)) + #self.setRenderHint(QPainter.HighQualityAntialiasing, self.fSavedSettings["Canvas/HighQualityAntialiasing"]) - pOptions = patchcanvas.options_t() - pOptions.theme_name = self.fSavedSettings["Canvas/Theme"] - pOptions.auto_hide_groups = self.fSavedSettings["Canvas/AutoHideGroups"] - pOptions.use_bezier_lines = self.fSavedSettings["Canvas/UseBezierLines"] - pOptions.antialiasing = self.fSavedSettings["Canvas/Antialiasing"] - pOptions.eyecandy = self.fSavedSettings["Canvas/EyeCandy"] + #pOptions = patchcanvas.options_t() + #pOptions.theme_name = self.fSavedSettings["Canvas/Theme"] + #pOptions.auto_hide_groups = self.fSavedSettings["Canvas/AutoHideGroups"] + #pOptions.use_bezier_lines = self.fSavedSettings["Canvas/UseBezierLines"] + #pOptions.antialiasing = self.fSavedSettings["Canvas/Antialiasing"] + #pOptions.eyecandy = self.fSavedSettings["Canvas/EyeCandy"] pFeatures = patchcanvas.features_t() pFeatures.group_info = False @@ -57,13 +80,319 @@ class CarlaPatchbayW(QWidget): pFeatures.port_rename = False pFeatures.handle_group_pos = True - patchcanvas.setOptions(pOptions) + #patchcanvas.setOptions(pOptions) patchcanvas.setFeatures(pFeatures) - patchcanvas.init("Carla", self.scene, canvasCallback, False) + patchcanvas.init("Carla", self.scene, CanvasCallback, True) + + #patchcanvas.setCanvasSize(0, 0, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT) + #patchcanvas.setInitialPos(DEFAULT_CANVAS_WIDTH / 2, DEFAULT_CANVAS_HEIGHT / 2) + #self.setSceneRect(0, 0, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT) + + # ----------------------------------------------------------------- + + def recheckPluginHints(self, hints): + pass + + # ----------------------------------------------------------------- + + def getPluginCount(self): + return self.fPluginCount + + def getPlugin(self, pluginId): + if pluginId >= self.fPluginCount: + return None + + pitem = self.fPluginList[pluginId] + if pitem is None: + return None + + return pitem + + # ----------------------------------------------------------------- + + def addPlugin(self, pluginId, isProjectLoading): + pitem = PluginEdit(self, pluginId) + + self.fPluginList.append(pitem) + self.fPluginCount += 1 + + def removePlugin(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + self.fPluginCount -= 1 + self.fPluginList.pop(pluginId) + + pitem.close() + del pitem + + # push all plugins 1 slot back + for i in range(pluginId, self.fPluginCount): + self.fPluginList[i].fPluginId = i # FIXME ? + + def renamePlugin(self, pluginId, newName): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.setName(name) + + def removeAllPlugins(self): + for i in range(self.fPluginCount): + pitem = self.fPluginList[i] + + if pitem is None: + break + + pitem.close() + del pitem + + self.fPluginCount = 0 + self.fPluginList = [] + + # ----------------------------------------------------------------- + + def setParameterValue(self, pluginId, index, value): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.setParameterValue(index, value) + + def setParameterDefault(self, pluginId, index, value): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.setParameterDefault(index, value) + + def setParameterMidiChannel(self, pluginId, index, channel): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.setParameterMidiChannel(index, channel) + + def setParameterMidiCC(self, pluginId, index, cc): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.setParameterMidiControl(index, cc) + + # ----------------------------------------------------------------- + + def setProgram(self, pluginId, index): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.setProgram(index) + + def setMidiProgram(self, pluginId, index): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.setMidiProgram(index) + + # ----------------------------------------------------------------- + + def noteOn(self, pluginId, channel, note, velocity): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.sendNoteOn(channel, note) + + def noteOff(self, pluginId, channel, note): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.sendNoteOff(channel, note) + + # ----------------------------------------------------------------- + + def setGuiState(self, pluginId, state): + pass + + # ----------------------------------------------------------------- + + def updateInfo(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.updateInfo() + + def reloadInfo(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.reloadInfo() + + def reloadParameters(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.reloadParameters() + + def reloadPrograms(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.reloadPrograms() + + def reloadAll(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.reloadAll() + + # ----------------------------------------------------------------- + + def patchbayClientAdded(self, clientId, clientIcon, clientName): + pcSplit = patchcanvas.SPLIT_UNDEF + pcIcon = patchcanvas.ICON_APPLICATION + + if clientIcon == PATCHBAY_ICON_HARDWARE: + pcSplit = patchcanvas.SPLIT_YES + pcIcon = patchcanvas.ICON_HARDWARE + elif clientIcon == PATCHBAY_ICON_DISTRHO: + pcIcon = patchcanvas.ICON_DISTRHO + elif clientIcon == PATCHBAY_ICON_FILE: + pcIcon = patchcanvas.ICON_FILE + elif clientIcon == PATCHBAY_ICON_PLUGIN: + pcIcon = patchcanvas.ICON_PLUGIN + + patchcanvas.addGroup(clientId, clientName, pcSplit, pcIcon) + #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) + + def patchbayClientRemoved(self, clientId, clientName): + #if not self.fEngineStarted: return + patchcanvas.removeGroup(clientId) + #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) + + def patchbayClientRenamed(self, clientId, newClientName): + patchcanvas.renameGroup(clientId, newClientName) + #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) + + def patchbayPortAdded(self, clientId, portId, portFlags, portName): + if (portFlags & PATCHBAY_PORT_IS_INPUT): + portMode = patchcanvas.PORT_MODE_INPUT + elif (portFlags & PATCHBAY_PORT_IS_OUTPUT): + portMode = patchcanvas.PORT_MODE_OUTPUT + else: + portMode = patchcanvas.PORT_MODE_NULL + + if (portFlags & PATCHBAY_PORT_IS_AUDIO): + portType = patchcanvas.PORT_TYPE_AUDIO_JACK + elif (portFlags & PATCHBAY_PORT_IS_MIDI): + portType = patchcanvas.PORT_TYPE_MIDI_JACK + else: + portType = patchcanvas.PORT_TYPE_NULL + + patchcanvas.addPort(clientId, portId, portName, portMode, portType) + #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) + + def patchbayPortRemoved(self, groupId, portId, fullPortName): + #if not self.fEngineStarted: return + patchcanvas.removePort(portId) + #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) + + def patchbayPortRenamed(self, groupId, portId, newPortName): + patchcanvas.renamePort(portId, newPortName) + #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) + + def patchbayConnectionAdded(self, connectionId, portOutId, portInId): + patchcanvas.connectPorts(connectionId, portOutId, portInId) + #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) + + def patchbayConnectionRemoved(self, connectionId): + #if not self.fEngineStarted: return + patchcanvas.disconnectPorts(connectionId) + #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) + + def patchbayIconChanged(self, clientId, clientIcon): + pcIcon = patchcanvas.ICON_APPLICATION + + if clientIcon == PATCHBAY_ICON_HARDWARE: + pcIcon = patchcanvas.ICON_HARDWARE + elif clientIcon == PATCHBAY_ICON_DISTRHO: + pcIcon = patchcanvas.ICON_DISTRHO + elif clientIcon == PATCHBAY_ICON_FILE: + pcIcon = patchcanvas.ICON_FILE + elif clientIcon == PATCHBAY_ICON_PLUGIN: + pcIcon = patchcanvas.ICON_PLUGIN + + patchcanvas.setGroupIcon(clientId, pcIcon) + + # ----------------------------------------------------------------- + + def idleFast(self): + pass + + def idleSlow(self): + for i in range(self.fPluginCount): + pitem = self.fPluginList[i] + + if pitem is None: + break + + pitem.idleSlow() - patchcanvas.setCanvasSize(0, 0, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT) - patchcanvas.setInitialPos(DEFAULT_CANVAS_WIDTH / 2, DEFAULT_CANVAS_HEIGHT / 2) - self.ui.graphicsView.setSceneRect(0, 0, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT) + # ----------------------------------------------------------------- @pyqtSlot() def slot_canvasArrange(self): diff --git a/source/carla_rack.py b/source/carla_rack.py index ddca200d4..012818d7e 100644 --- a/source/carla_rack.py +++ b/source/carla_rack.py @@ -48,12 +48,11 @@ class CarlaRackItem(QListWidgetItem): parent.setItemWidget(self, self.fWidget) + # ----------------------------------------------------------------- + def close(self): self.fWidget.ui.edit_dialog.close() - def getWidget(self): - return self.fWidget - def setId(self, idx): self.fWidget.setId(idx) @@ -73,10 +72,10 @@ class CarlaRackW(QListWidget): # ------------------------------------------------------------- # Set-up GUI stuff - self.setFixedWidth(800) + #self.setMnimumWidth(800) self.setSortingEnabled(False) - app = QApplication.instance() + app = QApplication.instance() pal1 = app.palette().base().color() pal2 = app.palette().button().color() col1 = "stop:0 rgb(%i, %i, %i)" % (pal1.red(), pal1.green(), pal1.blue()) @@ -93,34 +92,31 @@ class CarlaRackW(QListWidget): } """ % (col1, col2)) - # ------------------------------------------------------------- + # ----------------------------------------------------------------- - def idleFast(self): - for i in range(self.fPluginCount): - pitem = self.fPluginList[i] + def getPluginCount(self): + return self.fPluginCount - if pitem is None: - break - - pitem.fWidget.idleFast() + def getPlugin(self, pluginId): + if pluginId >= self.fPluginCount: + return None - def idleSlow(self): - for i in range(self.fPluginCount): - pitem = self.fPluginList[i] + pitem = self.fPluginList[pluginId] + if pitem is None: + return None - if pitem is None: - break + return pitem - pitem.fWidget.idleSlow() + # ----------------------------------------------------------------- - def addPlugin(self, pluginId): + def addPlugin(self, pluginId, isProjectLoading): pitem = CarlaRackItem(self, pluginId) self.fPluginList.append(pitem) self.fPluginCount += 1 - #if not self.fProjectLoading: - #pwidget.setActive(True, True, True) + if not isProjectLoading: + pitem.fWidget.setActive(True, True, True) def removePlugin(self, pluginId): if pluginId >= self.fPluginCount: @@ -142,6 +138,17 @@ class CarlaRackW(QListWidget): for i in range(pluginId, self.fPluginCount): self.fPluginList[i].setId(i) + def renamePlugin(self, pluginId, newName): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.fWidget.ui.label_name.setText(name) + pitem.fWidget.ui.edit_dialog.setName(name) + def removeAllPlugins(self): while (self.takeItem(0)): pass @@ -158,6 +165,213 @@ class CarlaRackW(QListWidget): self.fPluginCount = 0 self.fPluginList = [] + # ----------------------------------------------------------------- + + def setParameterValue(self, pluginId, index, value): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.fWidget.setParameterValue(index, value) + + def setParameterDefault(self, pluginId, index, value): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.fWidget.setParameterDefault(index, value) + + def setParameterMidiChannel(self, pluginId, index, channel): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.fWidget.setParameterMidiChannel(index, channel) + + def setParameterMidiCC(self, pluginId, index, cc): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.fWidget.setParameterMidiControl(index, cc) + + # ----------------------------------------------------------------- + + def setProgram(self, pluginId, index): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.fWidget.setProgram(index) + + def setMidiProgram(self, pluginId, index): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.fWidget.setMidiProgram(index) + + # ----------------------------------------------------------------- + + def noteOn(self, pluginId, channel, note, velocity): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.fWidget.sendNoteOn(channel, note) + + def noteOff(self, pluginId, channel, note): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.fWidget.sendNoteOff(channel, note) + + # ----------------------------------------------------------------- + + def setGuiState(self, pluginId, state): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + if state == 0: + pitem.fWidget.ui.b_gui.setChecked(False) + pitem.fWidget.ui.b_gui.setEnabled(True) + elif state == 1: + pitem.fWidget.ui.b_gui.setChecked(True) + pitem.fWidget.ui.b_gui.setEnabled(True) + elif state == -1: + pitem.fWidget.ui.b_gui.setChecked(False) + pitem.fWidget.ui.b_gui.setEnabled(False) + + # ----------------------------------------------------------------- + + def updateInfo(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.ui.edit_dialog.updateInfo() + + def reloadInfo(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.ui.edit_dialog.reloadInfo() + + def reloadParameters(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.ui.edit_dialog.reloadParameters() + + def reloadPrograms(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.ui.edit_dialog.reloadPrograms() + + def reloadAll(self, pluginId): + if pluginId >= self.fPluginCount: + return + + pitem = self.fPluginList[pluginId] + if pitem is None: + return + + pitem.ui.edit_dialog.reloadAll() + + # ----------------------------------------------------------------- + + def patchbayClientAdded(self, clientId, clientIcon, clientName): + pass + + def patchbayClientRemoved(self, clientId, clientName): + pass + + def patchbayClientRenamed(self, clientId, newClientName): + pass + + def patchbayPortAdded(self, clientId, portId, portFlags, portName): + pass + + def patchbayPortRemoved(self, groupId, portId, fullPortName): + pass + + def patchbayPortRenamed(self, groupId, portId, newPortName): + pass + + def patchbayConnectionAdded(self, connectionId, portOutId, portInId): + pass + + def patchbayConnectionRemoved(self, connectionId): + pass + + def patchbayIconChanged(self, clientId, clientIcon): + pass + + # ----------------------------------------------------------------- + + def idleFast(self): + for i in range(self.fPluginCount): + pitem = self.fPluginList[i] + + if pitem is None: + break + + pitem.fWidget.idleFast() + + def idleSlow(self): + for i in range(self.fPluginCount): + pitem = self.fPluginList[i] + + if pitem is None: + break + + pitem.fWidget.idleSlow() + # ------------------------------------------------------------------------------------------------------------ # TESTING diff --git a/source/carla_widgets.py b/source/carla_widgets.py index ff5d1bb18..9c4755c73 100644 --- a/source/carla_widgets.py +++ b/source/carla_widgets.py @@ -838,6 +838,10 @@ class PluginEdit(QDialog): self.fPlayingNotes = [] self.ui.keyboard.allNotesOff() + def setName(self, name): + self.ui.label_plugin.setText("\n%s\n" % name) + self.setWindowTitle(name) + def setParameterValue(self, parameterId, value): for paramItem in self.fParametersToUpdate: if paramItem[0] == parameterId: @@ -1490,9 +1494,6 @@ class PluginWidget(QFrame): self.ui.edit_dialog.clearNotes() self.ui.led_midi.setChecked(False) - def setParameterDefault(self, parameterId, value): - self.ui.edit_dialog.setParameterDefault(parameterId, value) - def setParameterValue(self, parameterId, value): self.fParameterIconTimer = ICON_STATE_ON @@ -1501,6 +1502,9 @@ class PluginWidget(QFrame): self.ui.edit_dialog.setParameterValue(parameterId, value) + def setParameterDefault(self, parameterId, value): + self.ui.edit_dialog.setParameterDefault(parameterId, value) + def setParameterMidiControl(self, parameterId, control): self.ui.edit_dialog.setParameterMidiControl(parameterId, control) diff --git a/source/patchcanvas.py b/source/patchcanvas.py index f831ff901..0a931eb12 100644 --- a/source/patchcanvas.py +++ b/source/patchcanvas.py @@ -16,17 +16,25 @@ # # For a full copy of the GNU General Public License see the GPL.txt file -# TODO - SIGNAL, SLOT - # Imports (Global) -from PyQt5.QtCore import pyqtSlot, qDebug, qCritical, qFatal, qWarning, Qt, QObject -from PyQt5.QtCore import QAbstractAnimation, QLineF, QPointF, QRectF, QSizeF, QSettings, QTimer -from PyQt5.QtGui import QColor, QLinearGradient, QPen, QPolygonF, QPainter, QPainterPath -from PyQt5.QtGui import QCursor, QFont, QFontMetrics -from PyQt5.QtSvg import QGraphicsSvgItem, QSvgRenderer -from PyQt5.QtWidgets import QGraphicsScene, QGraphicsItem, QGraphicsLineItem, QGraphicsPathItem -from PyQt5.QtWidgets import QGraphicsColorizeEffect, QGraphicsDropShadowEffect -from PyQt5.QtWidgets import QInputDialog, QLineEdit, QMenu +try: + from PyQt5.QtCore import pyqtSignal, pyqtSlot, qDebug, qCritical, qFatal, qWarning, Qt, QObject + from PyQt5.QtCore import QAbstractAnimation, QLineF, QPointF, QRectF, QSizeF, QSettings, QTimer + from PyQt5.QtGui import QColor, QLinearGradient, QPen, QPolygonF, QPainter, QPainterPath + from PyQt5.QtGui import QCursor, QFont, QFontMetrics + from PyQt5.QtSvg import QGraphicsSvgItem, QSvgRenderer + from PyQt5.QtWidgets import QGraphicsScene, QGraphicsItem, QGraphicsLineItem, QGraphicsPathItem + from PyQt5.QtWidgets import QGraphicsColorizeEffect, QGraphicsDropShadowEffect + from PyQt5.QtWidgets import QInputDialog, QLineEdit, QMenu +except: + from PyQt4.QtCore import pyqtSignal, pyqtSlot, qDebug, qCritical, qFatal, qWarning, Qt, QObject + from PyQt4.QtCore import QAbstractAnimation, QLineF, QPointF, QRectF, QSizeF, QSettings, QTimer + from PyQt4.QtGui import QColor, QLinearGradient, QPen, QPolygonF, QPainter, QPainterPath + from PyQt4.QtGui import QCursor, QFont, QFontMetrics + from PyQt4.QtGui import QGraphicsScene, QGraphicsItem, QGraphicsLineItem, QGraphicsPathItem + from PyQt4.QtGui import QGraphicsColorizeEffect, QGraphicsDropShadowEffect + from PyQt4.QtGui import QInputDialog, QLineEdit, QMenu + from PyQt4.QtSvg import QGraphicsSvgItem, QSvgRenderer # Imports (Theme) from patchcanvas_theme import * @@ -196,10 +204,6 @@ class CanvasObject(QObject): CanvasRemoveItemFX(item) CanvasRemoveAnimation(animation) - @pyqtSlot() - def CanvasPostponedGroups(self): - CanvasPostponedGroups() - @pyqtSlot() def PortContextMenuDisconnect(self): try: @@ -458,7 +462,7 @@ def addGroup(group_id, group_name, split=SPLIT_UNDEF, icon=ICON_APPLICATION): if options.eyecandy == EYECANDY_FULL and not options.auto_hide_groups: CanvasItemFX(group_box, True) - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) def removeGroup(group_id): if canvas.debug: @@ -498,7 +502,7 @@ def removeGroup(group_id): canvas.group_list.remove(group) - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::removeGroup(%i) - unable to find group to remove" % group_id) @@ -515,7 +519,7 @@ def renameGroup(group_id, new_group_name): if group.split and group.widgets[1]: group.widgets[1].setGroupName(new_group_name) - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::renameGroup(%i, %s) - unable to find group to rename" % (group_id, new_group_name.encode())) @@ -586,7 +590,7 @@ def splitGroup(group_id): for conn in conns_data: connectPorts(conn.connection_id, conn.port_out_id, conn.port_in_id) - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) def joinGroup(group_id): if canvas.debug: @@ -662,7 +666,7 @@ def joinGroup(group_id): for conn in conns_data: connectPorts(conn.connection_id, conn.port_out_id, conn.port_in_id) - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) def getGroupPos(group_id, port_mode=PORT_MODE_OUTPUT): if canvas.debug: @@ -697,7 +701,7 @@ def setGroupPosFull(group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group if group.split and group.widgets[1]: group.widgets[1].setPos(group_pos_x_i, group_pos_y_i) - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::setGroupPos(%i, %i, %i, %i, %i) - unable to find group to reposition" % (group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group_pos_y_i)) @@ -714,7 +718,7 @@ def setGroupIcon(group_id, icon): if group.split and group.widgets[1]: group.widgets[1].setIcon(icon) - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::setGroupIcon(%i, %s) - unable to find group to change icon" % (group_id, icon2str(icon))) @@ -759,7 +763,7 @@ def addPort(group_id, port_id, port_name, port_mode, port_type): box_widget.updatePositions() - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) def removePort(port_id): if canvas.debug: @@ -774,7 +778,7 @@ def removePort(port_id): canvas.port_list.remove(port) - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::removePort(%i) - Unable to find port to remove" % port_id) @@ -789,7 +793,7 @@ def renamePort(port_id, new_port_name): port.widget.setPortName(new_port_name) port.widget.parentItem().updatePositions() - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::renamePort(%i, %s) - Unable to find port to rename" % (port_id, new_port_name.encode())) @@ -826,6 +830,8 @@ def connectPorts(connection_id, port_out_id, port_in_id): else: connection_dict.widget = CanvasLine(port_out, port_in, None) + canvas.scene.addItem(connection_dict.widget) + port_out_parent.addLineFromGroup(connection_dict.widget, connection_id) port_in_parent.addLineFromGroup(connection_dict.widget, connection_id) @@ -842,7 +848,7 @@ def connectPorts(connection_id, port_out_id, port_in_id): item = connection_dict.widget CanvasItemFX(item, True) - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) def disconnectPorts(connection_id): if canvas.debug: @@ -891,7 +897,7 @@ def disconnectPorts(connection_id): else: line.deleteFromScene() - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) def arrange(): if canvas.debug: @@ -1008,10 +1014,6 @@ def CanvasRemoveAnimation(f_animation): del animation.animation break -def CanvasPostponedGroups(): - if canvas.debug: - qDebug("PatchCanvas::CanvasPostponedGroups()") - def CanvasCallback(action, value1, value2, value_str): if canvas.debug: qDebug("PatchCanvas::CanvasCallback(%i, %i, %i, %s)" % (action, value1, value2, value_str.encode())) @@ -1039,12 +1041,12 @@ def CanvasItemFX(item, show, destroy=False): canvas.animation_list.append(animation_dict) if show: - canvas.qobject.connect(animation, SIGNAL("finished()"), SLOT("AnimationIdle()")) + animation.finished.connect(canvas.qobject.AnimationIdle) else: if destroy: - canvas.qobject.connect(animation, SIGNAL("finished()"), SLOT("AnimationDestroy()")) + animation.finished.connect(canvas.qobject.AnimationDestroy) else: - canvas.qobject.connect(animation, SIGNAL("finished()"), SLOT("AnimationHide()")) + animation.finished.connect(canvas.qobject.AnimationHide) animation.start() @@ -1070,6 +1072,9 @@ def CanvasRemoveItemFX(item): # patchscene.cpp class PatchScene(QGraphicsScene): + scaleChanged = pyqtSignal(float) + sceneGroupMoved = pyqtSignal(int, int, QPointF) + def __init__(self, parent, view): QGraphicsScene.__init__(self, parent) @@ -1104,7 +1109,7 @@ class PatchScene(QGraphicsScene): elif scale < 0.2: self.m_view.resetTransform() self.m_view.scale(0.2, 0.2) - self.emit(SIGNAL("scaleChanged(double)"), self.m_view.transform().m11()) + self.scaleChanged.emit(self.m_view.transform().m11()) def updateTheme(self): self.setBackgroundBrush(canvas.theme.canvas_bg) @@ -1152,16 +1157,16 @@ class PatchScene(QGraphicsScene): def zoom_in(self): if self.m_view.transform().m11() < 3.0: self.m_view.scale(1.2, 1.2) - self.emit(SIGNAL("scaleChanged(double)"), self.m_view.transform().m11()) + self.scaleChanged.emit(self.m_view.transform().m11()) def zoom_out(self): if self.m_view.transform().m11() > 0.2: self.m_view.scale(0.8, 0.8) - self.emit(SIGNAL("scaleChanged(double)"), self.m_view.transform().m11()) + self.scaleChanged.emit(self.m_view.transform().m11()) def zoom_reset(self): self.m_view.resetTransform() - self.emit(SIGNAL("scaleChanged(double)"), 1.0) + self.scaleChanged.emit(1.0) def keyPressEvent(self, event): if not self.m_view: @@ -1247,7 +1252,7 @@ class PatchScene(QGraphicsScene): for item in items_list: if item and item.isVisible() and item.type() == CanvasBoxType: item.checkItemPos() - self.emit(SIGNAL("sceneGroupMoved(int, int, QPointF)"), item.getGroupId(), item.getSplittedMode(), item.scenePos()) + self.sceneGroupMoved.emit(item.getGroupId(), item.getSplittedMode(), item.scenePos()) if len(items_list) > 1: canvas.scene.update() @@ -1318,7 +1323,7 @@ class CanvasFadeAnimation(QAbstractAnimation): class CanvasLine(QGraphicsLineItem): def __init__(self, item1, item2, parent): - QGraphicsLineItem.__init__(self, parent, canvas.scene) + QGraphicsLineItem.__init__(self, parent) self.item1 = item1 self.item2 = item2 @@ -1414,7 +1419,7 @@ class CanvasLine(QGraphicsLineItem): class CanvasBezierLine(QGraphicsPathItem): def __init__(self, item1, item2, parent): - QGraphicsPathItem.__init__(self, parent, canvas.scene) + QGraphicsPathItem.__init__(self, parent) self.item1 = item1 self.item2 = item2 @@ -1521,7 +1526,7 @@ class CanvasBezierLine(QGraphicsPathItem): class CanvasLineMov(QGraphicsLineItem): def __init__(self, port_mode, port_type, parent): - QGraphicsLineItem.__init__(self, parent, canvas.scene) + QGraphicsLineItem.__init__(self, parent) self.m_port_mode = port_mode self.m_port_type = port_type @@ -1578,7 +1583,7 @@ class CanvasLineMov(QGraphicsLineItem): class CanvasBezierLineMov(QGraphicsPathItem): def __init__(self, port_mode, port_type, parent): - QGraphicsPathItem.__init__(self, parent, canvas.scene) + QGraphicsPathItem.__init__(self, parent) self.m_port_mode = port_mode self.m_port_type = port_type @@ -1642,7 +1647,7 @@ class CanvasBezierLineMov(QGraphicsPathItem): class CanvasPort(QGraphicsItem): def __init__(self, port_id, port_name, port_mode, port_type, parent): - QGraphicsItem.__init__(self, parent, canvas.scene) + QGraphicsItem.__init__(self, parent) # Save Variables, useful for later self.m_port_id = port_id @@ -1695,14 +1700,14 @@ class CanvasPort(QGraphicsItem): def setPortName(self, port_name): if QFontMetrics(self.m_port_font).width(port_name) < QFontMetrics(self.m_port_font).width(self.m_port_name): - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) self.m_port_name = port_name self.update() def setPortWidth(self, port_width): if port_width < self.m_port_width: - QTimer.singleShot(0, canvas.scene, SLOT("update()")) + QTimer.singleShot(0, canvas.scene.update) self.m_port_width = port_width self.update() @@ -1815,7 +1820,7 @@ class CanvasPort(QGraphicsItem): port_con_id = CanvasGetConnectedPort(port_id, self.m_port_id) act_x_disc = discMenu.addAction(CanvasGetFullPortName(port_con_id)) act_x_disc.setData(port_id) - QObject.connect(act_x_disc, SIGNAL("triggered()"), canvas.qobject, SLOT("PortContextMenuDisconnect()")) + act_x_disc.triggered.connect(canvas.qobject.PortContextMenuDisconnect) else: act_x_disc = discMenu.addAction("No connections") act_x_disc.setEnabled(False) @@ -1978,7 +1983,7 @@ class cb_line_t(object): class CanvasBox(QGraphicsItem): def __init__(self, group_id, group_name, icon, parent=None): - QGraphicsItem.__init__(self, parent, canvas.scene) + QGraphicsItem.__init__(self, parent) # Save Variables, useful for later self.m_group_id = group_id @@ -2026,6 +2031,8 @@ class CanvasBox(QGraphicsItem): self.updatePositions() + canvas.scene.addItem(self) + def getGroupId(self): return self.m_group_id @@ -2354,7 +2361,7 @@ class CanvasBox(QGraphicsItem): port_con_id = CanvasGetConnectedPort(port_con_list[i], port_con_list_ids[i]) act_x_disc = discMenu.addAction(CanvasGetFullPortName(port_con_id)) act_x_disc.setData(port_con_list[i]) - QObject.connect(act_x_disc, SIGNAL("triggered()"), canvas.qobject, SLOT("PortContextMenuDisconnect()")) + act_x_disc.triggered.connect(canvas.qobject.PortContextMenuDisconnect) else: act_x_disc = discMenu.addAction("No connections") act_x_disc.setEnabled(False) diff --git a/source/patchcanvas_theme.py b/source/patchcanvas_theme.py index 8e4e629eb..629697de9 100644 --- a/source/patchcanvas_theme.py +++ b/source/patchcanvas_theme.py @@ -19,8 +19,12 @@ # ------------------------------------------------------------------------------------------------------------ # Imports (Global) -from PyQt5.QtCore import Qt -from PyQt5.QtGui import QColor, QFont, QPen, QPixmap +try: + from PyQt5.QtCore import Qt + from PyQt5.QtGui import QColor, QFont, QPen, QPixmap +except: + from PyQt4.QtCore import Qt + from PyQt4.QtGui import QColor, QFont, QPen, QPixmap # ------------------------------------------------------------------------------------------------------------ # patchcanvas-theme.cpp diff --git a/source/plugin/Makefile b/source/plugin/Makefile index b2925c378..8b4d12ff9 100644 --- a/source/plugin/Makefile +++ b/source/plugin/Makefile @@ -30,12 +30,6 @@ endif # Common # LINK_FLAGS += $(shell pkg-config --libs liblo) -# -# ifeq ($(HAVE_QT4),true) -# LINK_FLAGS += $(shell pkg-config --libs QtCore QtGui QtXml) -# else -# LINK_FLAGS += $(shell pkg-config --libs Qt5Core Qt5Gui Qt5Xml Qt5Widgets) -# endif # -------------------------------------------------------------- # Plugin @@ -71,7 +65,7 @@ endif ifeq ($(HAVE_ZYN_DEPS),true) LINK_FLAGS += $(shell pkg-config --libs fftw3 mxml zlib) ifeq ($(HAVE_ZYN_UI_DEPS),true) -LINK_FLAGS += $(shell pkg-config --libs ntk ntk_images) +LINK_FLAGS += $(shell pkg-config --libs ntk_images ntk) -lfreetype # FIXME endif endif diff --git a/source/plugin/carla-native-base.cpp b/source/plugin/carla-native-base.cpp index bffdde809..1b0fe3731 100644 --- a/source/plugin/carla-native-base.cpp +++ b/source/plugin/carla-native-base.cpp @@ -57,6 +57,8 @@ void carla_register_native_plugin_PingPongPan(); #endif // DISTRHO plugins (PyQt) +void carla_register_native_plugin_BigMeter(); +void carla_register_native_plugin_BigMeterM(); void carla_register_native_plugin_Notes(); #ifdef WANT_ZYNADDSUBFX @@ -103,6 +105,8 @@ struct PluginListManager { #endif // DISTRHO plugins (PyQt) + carla_register_native_plugin_BigMeter(); + carla_register_native_plugin_BigMeterM(); carla_register_native_plugin_Notes(); // unfinished #ifdef WANT_ZYNADDSUBFX