| @@ -52,7 +52,7 @@ endif | |||
| BUILD_C_FLAGS = $(BASE_FLAGS) -std=gnu99 $(CFLAGS) | |||
| BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=gnu++0x $(CXXFLAGS) | |||
| LINK_FLAGS = $(LINK_OPTS) $(LDFLAGS) | |||
| LINK_FLAGS = $(LINK_OPTS) -Wl,--no-undefined $(LDFLAGS) | |||
| ifeq ($(MACOS),true) | |||
| # No C++11 support; force 32bit per default | |||
| @@ -16,8 +16,6 @@ ifeq ($(DEBUG),true) | |||
| BUILD_CXX_FLAGS += -D__RTAUDIO_DEBUG__ -D__RTMIDI_DEBUG__ | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| ifeq ($(HAVE_ALSA),true) | |||
| BUILD_CXX_FLAGS += $(shell pkg-config --cflags alsa) -D__LINUX_ALSA__ -D__LINUX_ALSASEQ__ | |||
| endif | |||
| @@ -84,7 +82,9 @@ HEADERS = \ | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
| $(TARGET): $(OBJS) | |||
| $(AR) rs $@ $^ | |||
| rm -f $@ | |||
| $(AR) crs $@ $^ | |||
| $(TARGETp): $(OBJSp) | |||
| $(AR) rs $@ $^ | |||
| rm -f $@ | |||
| $(AR) crs $@ $^ | |||
| @@ -10,14 +10,6 @@ include ../Makefile.mk | |||
| BUILD_CXX_FLAGS += $(shell pkg-config --cflags liblo) | |||
| # ifeq ($(HAVE_QT4),true) | |||
| # BUILD_CXX_FLAGS += $(shell pkg-config --cflags QtCore QtGui QtXml) | |||
| # else | |||
| # BUILD_CXX_FLAGS += $(shell pkg-config --cflags Qt5Core Qt5Gui Qt5Xml Qt5Widgets) | |||
| # endif | |||
| # -------------------------------------------------------------- | |||
| ifeq ($(HAVE_FLUIDSYNTH),true) | |||
| BUILD_CXX_FLAGS += $(shell pkg-config --cflags fluidsynth) | |||
| endif | |||
| @@ -30,7 +22,6 @@ endif | |||
| OBJS = \ | |||
| CarlaPlugin.cpp.o \ | |||
| CarlaPluginGui.cpp.o \ | |||
| CarlaPluginThread.cpp.o \ | |||
| BridgePlugin.cpp.o \ | |||
| NativePlugin.cpp.o \ | |||
| @@ -42,9 +33,6 @@ OBJS = \ | |||
| FluidSynthPlugin.cpp.o \ | |||
| LinuxSamplerPlugin.cpp.o | |||
| FILES = \ | |||
| moc_CarlaPluginGui.cpp | |||
| TARGET = ../libcarla_plugin.a | |||
| # -------------------------------------------------------------- | |||
| @@ -59,14 +47,9 @@ debug: | |||
| # -------------------------------------------------------------- | |||
| %.cpp.o: %.cpp ../CarlaBackend.hpp ../CarlaEngine.hpp ../CarlaPlugin.hpp CarlaPluginGui.hpp CarlaPluginInternal.hpp CarlaPluginThread.hpp | |||
| %.cpp.o: %.cpp ../CarlaBackend.hpp ../CarlaEngine.hpp ../CarlaPlugin.hpp CarlaPluginInternal.hpp CarlaPluginThread.hpp | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
| CarlaPluginGui.cpp.o: CarlaPluginGui.cpp moc_CarlaPluginGui.cpp CarlaPluginGui.hpp ../CarlaBackend.hpp ../CarlaEngine.hpp ../CarlaPlugin.hpp CarlaPluginInternal.hpp CarlaPluginThread.hpp | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
| moc_%.cpp: %.hpp | |||
| $(MOC) $< -DMOC_PARSING -o $@ | |||
| $(TARGET): $(OBJS) | |||
| $(AR) rs $@ $^ | |||
| rm -f $@ | |||
| $(AR) crs $@ $^ | |||
| @@ -8,7 +8,6 @@ include ../Makefile.mk | |||
| # -------------------------------------------------------------- | |||
| BUILD_CXX_FLAGS += -I../../modules/theme | |||
| BUILD_CXX_FLAGS += $(shell pkg-config --cflags liblo) | |||
| # -------------------------------------------------------------- | |||
| @@ -91,6 +90,8 @@ LIBS += ../libcarla_plugin.a | |||
| LIBS += ../../modules/carla_native.a | |||
| LIBS += ../../modules/juce_audio_basics.a | |||
| LIBS += ../../modules/juce_core.a | |||
| LIBS += ../../modules/juce_data_structures.a | |||
| LIBS += ../../modules/juce_events.a | |||
| LIBS += ../../modules/rtmempool.a | |||
| ifeq ($(CARLA_PLUGIN_SUPPORT),true) | |||
| @@ -0,0 +1,255 @@ | |||
| #!/usr/bin/env python3 | |||
| # -*- coding: utf-8 -*- | |||
| # Carla plugin host | |||
| # Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
| # | |||
| # This program is free software; you can redistribute it and/or | |||
| # modify it under the terms of the GNU General Public License as | |||
| # published by the Free Software Foundation; either version 2 of | |||
| # the License, or any later version. | |||
| # | |||
| # This program is distributed in the hope that it will be useful, | |||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| # GNU General Public License for more details. | |||
| # | |||
| # For a full copy of the GNU General Public License see the GPL.txt file | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Global) | |||
| try: | |||
| from PyQt5.QtWidgets import QApplication, QMainWindow | |||
| except: | |||
| from PyQt4.QtGui import QApplication, QMainWindow | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Custom Stuff) | |||
| from carla_database import * | |||
| from carla_rack import * | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Main Window | |||
| class CarlaMiniW(QMainWindow): | |||
| def __init__(self, parent=None): | |||
| QMainWindow.__init__(self, parent) | |||
| #self.ui = ui_carla.Ui_CarlaMainW() | |||
| #self.ui.setupUi(self) | |||
| Carla.host.engine_init("JACK", "Carla") | |||
| self.fRack = CarlaRackW(self) | |||
| self.setCentralWidget(self.fRack) | |||
| self.fIdleTimerFast = self.startTimer(50) | |||
| self.fIdleTimerSlow = self.startTimer(50*2) | |||
| QTimer.singleShot(0, self.slot_pluginAdd) | |||
| def closeEvent(self, event): | |||
| self.fIdleTimerFast = 0 | |||
| self.fIdleTimerSlow = 0 | |||
| Carla.host.engine_close() | |||
| QMainWindow.closeEvent(self, event) | |||
| def timerEvent(self, event): | |||
| if event.timerId() == self.fIdleTimerFast: | |||
| Carla.host.engine_idle() | |||
| self.fRack.idleFast() | |||
| elif event.timerId() == self.fIdleTimerSlow: | |||
| self.fRack.idleSlow() | |||
| QMainWindow.timerEvent(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.fRack.addPlugin(0) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| def engineCallback(ptr, action, pluginId, value1, value2, value3, valueStr): | |||
| if pluginId < 0 or not Carla.gui: | |||
| return | |||
| #if action == CALLBACK_DEBUG: | |||
| #Carla.gui.emit(SIGNAL("DebugCallback(int, int, int, double, QString)"), pluginId, value1, value2, value3, cString(valueStr)) | |||
| #elif action == CALLBACK_PLUGIN_ADDED: | |||
| #Carla.gui.emit(SIGNAL("PluginAddedCallback(int)"), pluginId) | |||
| #elif action == CALLBACK_PLUGIN_REMOVED: | |||
| #Carla.gui.emit(SIGNAL("PluginRemovedCallback(int)"), pluginId) | |||
| #elif action == CALLBACK_PLUGIN_RENAMED: | |||
| #Carla.gui.emit(SIGNAL("PluginRenamedCallback(int, QString)"), pluginId, valueStr) | |||
| #elif action == CALLBACK_PARAMETER_VALUE_CHANGED: | |||
| #Carla.gui.emit(SIGNAL("ParameterValueChangedCallback(int, int, double)"), pluginId, value1, value3) | |||
| #elif action == CALLBACK_PARAMETER_DEFAULT_CHANGED: | |||
| #Carla.gui.emit(SIGNAL("ParameterDefaultChangedCallback(int, int, double)"), pluginId, value1, value3) | |||
| #elif action == CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED: | |||
| #Carla.gui.emit(SIGNAL("ParameterMidiChannelChangedCallback(int, int, int)"), pluginId, value1, value2) | |||
| #elif action == CALLBACK_PARAMETER_MIDI_CC_CHANGED: | |||
| #Carla.gui.emit(SIGNAL("ParameterMidiCcChangedCallback(int, int, int)"), pluginId, value1, value2) | |||
| #elif action == CALLBACK_PROGRAM_CHANGED: | |||
| #Carla.gui.emit(SIGNAL("ProgramChangedCallback(int, int)"), pluginId, value1) | |||
| #elif action == CALLBACK_MIDI_PROGRAM_CHANGED: | |||
| #Carla.gui.emit(SIGNAL("MidiProgramChangedCallback(int, int)"), pluginId, value1) | |||
| #elif action == CALLBACK_NOTE_ON: | |||
| #Carla.gui.emit(SIGNAL("NoteOnCallback(int, int, int, int)"), pluginId, value1, value2, value3) | |||
| #elif action == CALLBACK_NOTE_OFF: | |||
| #Carla.gui.emit(SIGNAL("NoteOffCallback(int, int, int)"), pluginId, value1, value2) | |||
| #elif action == CALLBACK_SHOW_GUI: | |||
| #Carla.gui.emit(SIGNAL("ShowGuiCallback(int, int)"), pluginId, value1) | |||
| #elif action == CALLBACK_UPDATE: | |||
| #Carla.gui.emit(SIGNAL("UpdateCallback(int)"), pluginId) | |||
| #elif action == CALLBACK_RELOAD_INFO: | |||
| #Carla.gui.emit(SIGNAL("ReloadInfoCallback(int)"), pluginId) | |||
| #elif action == CALLBACK_RELOAD_PARAMETERS: | |||
| #Carla.gui.emit(SIGNAL("ReloadParametersCallback(int)"), pluginId) | |||
| #elif action == CALLBACK_RELOAD_PROGRAMS: | |||
| #Carla.gui.emit(SIGNAL("ReloadProgramsCallback(int)"), pluginId) | |||
| #elif action == CALLBACK_RELOAD_ALL: | |||
| #Carla.gui.emit(SIGNAL("ReloadAllCallback(int)"), pluginId) | |||
| #elif action == CALLBACK_PATCHBAY_CLIENT_ADDED: | |||
| #Carla.gui.emit(SIGNAL("PatchbayClientAddedCallback(int, int, QString)"), value1, value2, cString(valueStr)) | |||
| #elif action == CALLBACK_PATCHBAY_CLIENT_REMOVED: | |||
| #Carla.gui.emit(SIGNAL("PatchbayClientRemovedCallback(int, QString)"), value1, cString(valueStr)) | |||
| #elif action == CALLBACK_PATCHBAY_CLIENT_RENAMED: | |||
| #Carla.gui.emit(SIGNAL("PatchbayClientRenamedCallback(int, QString)"), value1, cString(valueStr)) | |||
| #elif action == CALLBACK_PATCHBAY_PORT_ADDED: | |||
| #Carla.gui.emit(SIGNAL("PatchbayPortAddedCallback(int, int, int, QString)"), value1, value2, int(value3), cString(valueStr)) | |||
| #elif action == CALLBACK_PATCHBAY_PORT_REMOVED: | |||
| #Carla.gui.emit(SIGNAL("PatchbayPortRemovedCallback(int, int, QString)"), value1, value2, cString(valueStr)) | |||
| #elif action == CALLBACK_PATCHBAY_PORT_RENAMED: | |||
| #Carla.gui.emit(SIGNAL("PatchbayPortRenamedCallback(int, int, QString)"), value1, value2, cString(valueStr)) | |||
| #elif action == CALLBACK_PATCHBAY_CONNECTION_ADDED: | |||
| #Carla.gui.emit(SIGNAL("PatchbayConnectionAddedCallback(int, int, int)"), value1, value2, value3) | |||
| #elif action == CALLBACK_PATCHBAY_CONNECTION_REMOVED: | |||
| #Carla.gui.emit(SIGNAL("PatchbayConnectionRemovedCallback(int)"), value1) | |||
| #elif action == CALLBACK_PATCHBAY_ICON_CHANGED: | |||
| #Carla.gui.emit(SIGNAL("PatchbayIconChangedCallback(int, int)"), value1, value2) | |||
| #elif action == CALLBACK_BUFFER_SIZE_CHANGED: | |||
| #Carla.gui.emit(SIGNAL("BufferSizeChangedCallback(int)"), value1) | |||
| #elif action == CALLBACK_SAMPLE_RATE_CHANGED: | |||
| #Carla.gui.emit(SIGNAL("SampleRateChangedCallback(double)"), value3) | |||
| #elif action == CALLBACK_NSM_ANNOUNCE: | |||
| #Carla.gui.emit(SIGNAL("NSM_AnnounceCallback(QString)"), cString(valueStr)) | |||
| #elif action == CALLBACK_NSM_OPEN: | |||
| #Carla.gui.emit(SIGNAL("NSM_OpenCallback(QString)"), cString(valueStr)) | |||
| #elif action == CALLBACK_NSM_SAVE: | |||
| #Carla.gui.emit(SIGNAL("NSM_SaveCallback()")) | |||
| #elif action == CALLBACK_ERROR: | |||
| #Carla.gui.emit(SIGNAL("ErrorCallback(QString)"), cString(valueStr)) | |||
| #elif action == CALLBACK_QUIT: | |||
| #Carla.gui.emit(SIGNAL("QuitCallback()")) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # --------------- main ------------------ | |||
| if __name__ == '__main__': | |||
| # App initialization | |||
| app = QApplication(sys.argv) | |||
| app.setApplicationName("Carla") | |||
| app.setApplicationVersion(VERSION) | |||
| app.setOrganizationName("falkTX") | |||
| app.setWindowIcon(QIcon(":/scalable/carla.svg")) | |||
| libName = carla_library_filename | |||
| libPath = carla_library_filename.replace(carla_libname, "") | |||
| # Init backend | |||
| print("libName:", libName, ":", carla_libname) | |||
| Carla.host = Host(libName) | |||
| Carla.host.set_engine_option(OPTION_PROCESS_NAME, 0, "carla") | |||
| Carla.host.set_engine_option(OPTION_PATH_RESOURCES, 0, libPath) | |||
| # Set bridge paths | |||
| if carla_bridge_native: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_NATIVE, 0, carla_bridge_native) | |||
| if carla_bridge_posix32: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_POSIX32, 0, carla_bridge_posix32) | |||
| if carla_bridge_posix64: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_POSIX64, 0, carla_bridge_posix64) | |||
| if carla_bridge_win32: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_WIN32, 0, carla_bridge_win32) | |||
| if carla_bridge_win64: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_WIN64, 0, carla_bridge_win64) | |||
| if carla_bridge_lv2_external: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_EXTERNAL, 0, carla_bridge_lv2_external) | |||
| if WINDOWS: | |||
| if carla_bridge_lv2_windows: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_WINDOWS, 0, carla_bridge_lv2_windows) | |||
| if carla_bridge_vst_hwnd: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_VST_HWND, 0, carla_bridge_vst_hwnd) | |||
| elif MACOS: | |||
| if carla_bridge_lv2_cocoa: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_COCOA, 0, carla_bridge_lv2_cocoa) | |||
| if carla_bridge_vst_mac: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_VST_MAC, 0, carla_bridge_vst_mac) | |||
| else: | |||
| if carla_bridge_lv2_gtk2: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_GTK2, 0, carla_bridge_lv2_gtk2) | |||
| if carla_bridge_lv2_gtk3: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_GTK3, 0, carla_bridge_lv2_gtk3) | |||
| if carla_bridge_lv2_qt4: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_QT4, 0, carla_bridge_lv2_qt4) | |||
| if carla_bridge_lv2_qt5: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_QT5, 0, carla_bridge_lv2_qt5) | |||
| if carla_bridge_lv2_x11: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_X11, 0, carla_bridge_lv2_x11) | |||
| if carla_bridge_vst_x11: | |||
| Carla.host.set_engine_option(OPTION_PATH_BRIDGE_VST_X11, 0, carla_bridge_vst_x11) | |||
| # Create GUI and start engine | |||
| Carla.gui = CarlaMiniW() | |||
| # Only now we're ready to handle events | |||
| Carla.host.set_engine_callback(engineCallback) | |||
| # Set-up custom signal handling | |||
| setUpSignals() | |||
| # Show GUI | |||
| Carla.gui.show() | |||
| # App-Loop | |||
| ret = app.exec_() | |||
| # Destroy GUI | |||
| tmp = Carla.gui | |||
| Carla.gui = None | |||
| del tmp | |||
| # Exit properly | |||
| sys.exit(ret) | |||
| @@ -28,7 +28,6 @@ from PyQt5.QtWidgets import QApplication, QDialogButtonBox, QFileSystemModel, QL | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Custom Stuff) | |||
| import patchcanvas | |||
| import ui_carla | |||
| from carla_shared import * | |||
| @@ -108,9 +107,6 @@ class CarlaMainW(QMainWindow): | |||
| self.fProjectFilename = None | |||
| self.fProjectLoading = False | |||
| self.fPluginCount = 0 | |||
| self.fPluginList = [] | |||
| self.fIdleTimerFast = 0 | |||
| self.fIdleTimerSlow = 0 | |||
| @@ -164,38 +160,6 @@ class CarlaMainW(QMainWindow): | |||
| self.ui.tabMain.setCurrentIndex(1) | |||
| self.ui.tabMain.setCurrentIndex(0) | |||
| # ------------------------------------------------------------- | |||
| # 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"]) | |||
| 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) | |||
| 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) | |||
| # ------------------------------------------------------------- | |||
| # Set-up Canvas Preview | |||
| @@ -880,73 +844,6 @@ class CarlaMainW(QMainWindow): | |||
| newFrame = Carla.host.get_current_transport_frame() + 100000 | |||
| Carla.host.transport_relocate(newFrame) | |||
| @pyqtSlot() | |||
| def slot_canvasArrange(self): | |||
| patchcanvas.arrange() | |||
| @pyqtSlot() | |||
| def slot_canvasRefresh(self): | |||
| patchcanvas.clear() | |||
| if Carla.host.is_engine_running(): | |||
| Carla.host.patchbay_refresh() | |||
| QTimer.singleShot(1000 if self.fSavedSettings['Canvas/EyeCandy'] else 0, self.ui.miniCanvasPreview, SLOT("update()")) | |||
| @pyqtSlot() | |||
| def slot_canvasZoomFit(self): | |||
| self.scene.zoom_fit() | |||
| @pyqtSlot() | |||
| def slot_canvasZoomIn(self): | |||
| self.scene.zoom_in() | |||
| @pyqtSlot() | |||
| def slot_canvasZoomOut(self): | |||
| self.scene.zoom_out() | |||
| @pyqtSlot() | |||
| def slot_canvasZoomReset(self): | |||
| self.scene.zoom_reset() | |||
| @pyqtSlot() | |||
| def slot_canvasPrint(self): | |||
| self.scene.clearSelection() | |||
| self.fExportPrinter = QPrinter() | |||
| dialog = QPrintDialog(self.fExportPrinter, self) | |||
| if dialog.exec_(): | |||
| painter = QPainter(self.fExportPrinter) | |||
| painter.save() | |||
| painter.setRenderHint(QPainter.Antialiasing) | |||
| painter.setRenderHint(QPainter.TextAntialiasing) | |||
| self.scene.render(painter) | |||
| painter.restore() | |||
| @pyqtSlot() | |||
| def slot_canvasSaveImage(self): | |||
| newPath = QFileDialog.getSaveFileName(self, self.tr("Save Image"), filter=self.tr("PNG Image (*.png);;JPEG Image (*.jpg)")) | |||
| if newPath: | |||
| self.scene.clearSelection() | |||
| # FIXME - must be a better way... | |||
| if newPath.endswith((".jpg", ".jpG", ".jPG", ".JPG", ".JPg", ".Jpg")): | |||
| imgFormat = "JPG" | |||
| elif newPath.endswith((".png", ".pnG", ".pNG", ".PNG", ".PNg", ".Png")): | |||
| imgFormat = "PNG" | |||
| else: | |||
| # File-dialog may not auto-add the extension | |||
| imgFormat = "PNG" | |||
| newPath += ".png" | |||
| self.fExportImage = QImage(self.scene.sceneRect().width(), self.scene.sceneRect().height(), QImage.Format_RGB32) | |||
| painter = QPainter(self.fExportImage) | |||
| painter.save() | |||
| painter.setRenderHint(QPainter.Antialiasing) # TODO - set true, cleanup this | |||
| painter.setRenderHint(QPainter.TextAntialiasing) | |||
| self.scene.render(painter) | |||
| self.fExportImage.save(newPath, imgFormat, 100) | |||
| painter.restore() | |||
| @pyqtSlot() | |||
| def slot_toolbarShown(self): | |||
| self.updateInfoLabelPos() | |||
| @@ -1473,22 +1370,6 @@ class CarlaMainW(QMainWindow): | |||
| folder = diskFolders[i] | |||
| self.ui.cb_disk.addItem(os.path.basename(folder), folder) | |||
| pal1 = app.palette().base().color() | |||
| pal2 = app.palette().button().color() | |||
| col1 = "stop:0 rgb(%i, %i, %i)" % (pal1.red(), pal1.green(), pal1.blue()) | |||
| col2 = "stop:1 rgb(%i, %i, %i)" % (pal2.red(), pal2.green(), pal2.blue()) | |||
| self.setStyleSheet(""" | |||
| QWidget#w_plugins { | |||
| background-color: qlineargradient(spread:pad, | |||
| x1:0.0, y1:0.0, | |||
| x2:0.2, y2:1.0, | |||
| %s, | |||
| %s | |||
| ); | |||
| } | |||
| """ % (col1, col2)) | |||
| if MACOS and not settings.value("Main/UseProTheme", True, type=bool): | |||
| self.setUnifiedTitleAndToolBarOnMac(True) | |||
| @@ -1620,44 +1501,6 @@ class CarlaMainW(QMainWindow): | |||
| QMainWindow.closeEvent(self, event) | |||
| # ------------------------------------------------------------------------------------------------ | |||
| def canvasCallback(action, value1, value2, valueStr): | |||
| if action == patchcanvas.ACTION_GROUP_INFO: | |||
| pass | |||
| elif action == patchcanvas.ACTION_GROUP_RENAME: | |||
| pass | |||
| elif action == patchcanvas.ACTION_GROUP_SPLIT: | |||
| groupId = value1 | |||
| patchcanvas.splitGroup(groupId) | |||
| Carla.gui.ui.miniCanvasPreview.update() | |||
| elif action == patchcanvas.ACTION_GROUP_JOIN: | |||
| groupId = value1 | |||
| patchcanvas.joinGroup(groupId) | |||
| Carla.gui.ui.miniCanvasPreview.update() | |||
| elif action == patchcanvas.ACTION_PORT_INFO: | |||
| pass | |||
| elif action == patchcanvas.ACTION_PORT_RENAME: | |||
| pass | |||
| elif action == patchcanvas.ACTION_PORTS_CONNECT: | |||
| portIdA = value1 | |||
| portIdB = value2 | |||
| if not Carla.host.patchbay_connect(portIdA, portIdB): | |||
| print("Connection failed:", cString(Carla.host.get_last_error())) | |||
| elif action == patchcanvas.ACTION_PORTS_DISCONNECT: | |||
| connectionId = value1 | |||
| if not Carla.host.patchbay_disconnect(connectionId): | |||
| print("Disconnect failed:", cString(Carla.host.get_last_error())) | |||
| def engineCallback(ptr, action, pluginId, value1, value2, value3, valueStr): | |||
| if pluginId < 0 or not Carla.gui: | |||
| return | |||
| @@ -1664,8 +1664,8 @@ class PluginDatabaseW(QDialog): | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # TESTING | |||
| from PyQt5.QtWidgets import QApplication | |||
| app = QApplication(sys.argv) | |||
| gui = PluginDatabaseW(None) | |||
| gui.show() | |||
| app.exec_() | |||
| #from PyQt5.QtWidgets import QApplication | |||
| #app = QApplication(sys.argv) | |||
| #gui = PluginDatabaseW(None) | |||
| #gui.show() | |||
| #app.exec_() | |||
| @@ -0,0 +1,172 @@ | |||
| #!/usr/bin/env python3 | |||
| # -*- coding: utf-8 -*- | |||
| # Carla patchbay widget code | |||
| # Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
| # | |||
| # This program is free software; you can redistribute it and/or | |||
| # modify it under the terms of the GNU General Public License as | |||
| # published by the Free Software Foundation; either version 2 of | |||
| # the License, or any later version. | |||
| # | |||
| # This program is distributed in the hope that it will be useful, | |||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| # GNU General Public License for more details. | |||
| # | |||
| # For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Global) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Custom Stuff) | |||
| import patchcanvas | |||
| from carla_widgets import * | |||
| # ------------------------------------------------------------------------------------------------ | |||
| # Patchbay widget | |||
| class CarlaPatchbayW(QWidget): | |||
| def __init__(self, parent): | |||
| QWidget.__init__(self, parent) | |||
| # ------------------------------------------------------------- | |||
| # 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"]) | |||
| 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) | |||
| 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): | |||
| patchcanvas.arrange() | |||
| @pyqtSlot() | |||
| def slot_canvasRefresh(self): | |||
| patchcanvas.clear() | |||
| if Carla.host.is_engine_running(): | |||
| Carla.host.patchbay_refresh() | |||
| QTimer.singleShot(1000 if self.fSavedSettings['Canvas/EyeCandy'] else 0, self.ui.miniCanvasPreview, SLOT("update()")) | |||
| @pyqtSlot() | |||
| def slot_canvasZoomFit(self): | |||
| self.scene.zoom_fit() | |||
| @pyqtSlot() | |||
| def slot_canvasZoomIn(self): | |||
| self.scene.zoom_in() | |||
| @pyqtSlot() | |||
| def slot_canvasZoomOut(self): | |||
| self.scene.zoom_out() | |||
| @pyqtSlot() | |||
| def slot_canvasZoomReset(self): | |||
| self.scene.zoom_reset() | |||
| @pyqtSlot() | |||
| def slot_canvasPrint(self): | |||
| self.scene.clearSelection() | |||
| self.fExportPrinter = QPrinter() | |||
| dialog = QPrintDialog(self.fExportPrinter, self) | |||
| if dialog.exec_(): | |||
| painter = QPainter(self.fExportPrinter) | |||
| painter.save() | |||
| painter.setRenderHint(QPainter.Antialiasing) | |||
| painter.setRenderHint(QPainter.TextAntialiasing) | |||
| self.scene.render(painter) | |||
| painter.restore() | |||
| @pyqtSlot() | |||
| def slot_canvasSaveImage(self): | |||
| newPath = QFileDialog.getSaveFileName(self, self.tr("Save Image"), filter=self.tr("PNG Image (*.png);;JPEG Image (*.jpg)")) | |||
| if newPath: | |||
| self.scene.clearSelection() | |||
| # FIXME - must be a better way... | |||
| if newPath.endswith((".jpg", ".jpG", ".jPG", ".JPG", ".JPg", ".Jpg")): | |||
| imgFormat = "JPG" | |||
| elif newPath.endswith((".png", ".pnG", ".pNG", ".PNG", ".PNg", ".Png")): | |||
| imgFormat = "PNG" | |||
| else: | |||
| # File-dialog may not auto-add the extension | |||
| imgFormat = "PNG" | |||
| newPath += ".png" | |||
| self.fExportImage = QImage(self.scene.sceneRect().width(), self.scene.sceneRect().height(), QImage.Format_RGB32) | |||
| painter = QPainter(self.fExportImage) | |||
| painter.save() | |||
| painter.setRenderHint(QPainter.Antialiasing) # TODO - set true, cleanup this | |||
| painter.setRenderHint(QPainter.TextAntialiasing) | |||
| self.scene.render(painter) | |||
| self.fExportImage.save(newPath, imgFormat, 100) | |||
| painter.restore() | |||
| # ------------------------------------------------------------------------------------------------ | |||
| # ... | |||
| def canvasCallback(action, value1, value2, valueStr): | |||
| if action == patchcanvas.ACTION_GROUP_INFO: | |||
| pass | |||
| elif action == patchcanvas.ACTION_GROUP_RENAME: | |||
| pass | |||
| elif action == patchcanvas.ACTION_GROUP_SPLIT: | |||
| groupId = value1 | |||
| patchcanvas.splitGroup(groupId) | |||
| Carla.gui.ui.miniCanvasPreview.update() | |||
| elif action == patchcanvas.ACTION_GROUP_JOIN: | |||
| groupId = value1 | |||
| patchcanvas.joinGroup(groupId) | |||
| Carla.gui.ui.miniCanvasPreview.update() | |||
| elif action == patchcanvas.ACTION_PORT_INFO: | |||
| pass | |||
| elif action == patchcanvas.ACTION_PORT_RENAME: | |||
| pass | |||
| elif action == patchcanvas.ACTION_PORTS_CONNECT: | |||
| portIdA = value1 | |||
| portIdB = value2 | |||
| if not Carla.host.patchbay_connect(portIdA, portIdB): | |||
| print("Connection failed:", cString(Carla.host.get_last_error())) | |||
| elif action == patchcanvas.ACTION_PORTS_DISCONNECT: | |||
| connectionId = value1 | |||
| if not Carla.host.patchbay_disconnect(connectionId): | |||
| print("Disconnect failed:", cString(Carla.host.get_last_error())) | |||
| @@ -0,0 +1,183 @@ | |||
| #!/usr/bin/env python3 | |||
| # -*- coding: utf-8 -*- | |||
| # Carla rack widget code | |||
| # Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
| # | |||
| # This program is free software; you can redistribute it and/or | |||
| # modify it under the terms of the GNU General Public License as | |||
| # published by the Free Software Foundation; either version 2 of | |||
| # the License, or any later version. | |||
| # | |||
| # This program is distributed in the hope that it will be useful, | |||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| # GNU General Public License for more details. | |||
| # | |||
| # For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Global) | |||
| try: | |||
| from PyQt5.QtCore import QSize, QTimer | |||
| from PyQt5.QtWidgets import QApplication, QListWidget, QListWidgetItem | |||
| except: | |||
| from PyQt4.QtCore import QSize, QTimer | |||
| from PyQt4.QtGui import QApplication, QListWidget, QListWidgetItem | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Custom Stuff) | |||
| from carla_widgets import * | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Rack widget item | |||
| class CarlaRackItem(QListWidgetItem): | |||
| RackItemType = QListWidgetItem.UserType + 1 | |||
| StaticHeight = 32 | |||
| def __init__(self, parent, pluginId): | |||
| QListWidgetItem.__init__(self, parent, self.RackItemType) | |||
| self.fWidget = PluginWidget(parent, pluginId) | |||
| self.fWidget.setFixedHeight(self.StaticHeight) | |||
| self.setSizeHint(QSize(300, self.StaticHeight)) | |||
| 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) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Rack widget | |||
| class CarlaRackW(QListWidget): | |||
| def __init__(self, parent): | |||
| QListWidget.__init__(self, parent) | |||
| # ------------------------------------------------------------- | |||
| # Internal stuff | |||
| self.fPluginCount = 0 | |||
| self.fPluginList = [] | |||
| # ------------------------------------------------------------- | |||
| # Set-up GUI stuff | |||
| self.setFixedWidth(800) | |||
| self.setSortingEnabled(False) | |||
| 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()) | |||
| col2 = "stop:1 rgb(%i, %i, %i)" % (pal2.red(), pal2.green(), pal2.blue()) | |||
| self.setStyleSheet(""" | |||
| QListWidget { | |||
| background-color: qlineargradient(spread:pad, | |||
| x1:0.0, y1:0.0, | |||
| x2:0.2, y2:1.0, | |||
| %s, | |||
| %s | |||
| ); | |||
| } | |||
| """ % (col1, col2)) | |||
| # ------------------------------------------------------------- | |||
| # TESTING | |||
| #self.addPlugin(0) | |||
| #self.addPlugin(1) | |||
| #self.addPlugin(2) | |||
| #self.addPlugin(3) | |||
| #self.addPlugin(4) | |||
| #self.removePlugin(3) | |||
| #QTimer.singleShot(3000, self.testRemove) | |||
| #QTimer.singleShot(5000, self.removeAllPlugins) | |||
| def testRemove(self): | |||
| self.removePlugin(0) | |||
| 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() | |||
| def addPlugin(self, pluginId): | |||
| pitem = CarlaRackItem(self, pluginId) | |||
| self.fPluginList.append(pitem) | |||
| self.fPluginCount += 1 | |||
| #if not self.fProjectLoading: | |||
| #pwidget.setActive(True, True, True) | |||
| 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) | |||
| self.takeItem(pluginId) | |||
| pitem.close() | |||
| del pitem | |||
| # push all plugins 1 slot back | |||
| for i in range(pluginId, self.fPluginCount): | |||
| self.fPluginList[i].setId(i) | |||
| def removeAllPlugins(self): | |||
| while (self.takeItem(0)): | |||
| pass | |||
| for i in range(self.fPluginCount): | |||
| pitem = self.fPluginList[i] | |||
| if pitem is None: | |||
| break | |||
| pitem.close() | |||
| del pitem | |||
| self.fPluginCount = 0 | |||
| self.fPluginList = [] | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # TESTING | |||
| #from PyQt5.QtWidgets import QApplication | |||
| #app = QApplication(sys.argv) | |||
| #gui = CarlaRackW(None) | |||
| #gui.show() | |||
| #app.exec_() | |||
| @@ -326,7 +326,7 @@ Carla = CarlaObject() | |||
| Carla.host = None | |||
| Carla.gui = None | |||
| Carla.isControl = False | |||
| Carla.isLocal = False | |||
| Carla.isLocal = True | |||
| Carla.processMode = PROCESS_MODE_MULTIPLE_CLIENTS if LINUX else PROCESS_MODE_CONTINUOUS_RACK | |||
| Carla.maxParameters = MAX_DEFAULT_PARAMETERS | |||
| @@ -402,7 +402,7 @@ carla_bridge_vst_mac = "" | |||
| carla_bridge_vst_hwnd = "" | |||
| carla_bridge_vst_x11 = "" | |||
| carla_libname = "libcarla_%s" % "control" if Carla.isControl else "standalone" | |||
| carla_libname = "libcarla_%s" % ("control" if Carla.isControl else "standalone") | |||
| if WINDOWS: | |||
| carla_libname += ".dll" | |||
| @@ -373,6 +373,8 @@ class PluginParameter(QWidget): | |||
| # Plugin Editor (Built-in) | |||
| class PluginEdit(QDialog): | |||
| ParamsPerPage = 8 | |||
| def __init__(self, parent, pluginId): | |||
| QDialog.__init__(self, Carla.gui) | |||
| self.ui = ui_carla_edit.Ui_PluginEdit() | |||
| @@ -685,7 +687,7 @@ class PluginEdit(QDialog): | |||
| paramInputList.append(parameter) | |||
| if len(paramInputList) == 10: | |||
| if len(paramInputList) == self.ParamsPerPage: | |||
| paramInputListFull.append((paramInputList, paramInputWidth)) | |||
| paramInputList = [] | |||
| paramInputWidth = 0 | |||
| @@ -698,7 +700,7 @@ class PluginEdit(QDialog): | |||
| paramOutputList.append(parameter) | |||
| if len(paramOutputList) == 10: | |||
| if len(paramOutputList) == self.ParamsPerPage: | |||
| paramOutputListFull.append((paramOutputList, paramOutputWidth)) | |||
| paramOutputList = [] | |||
| paramOutputWidth = 0 | |||
| @@ -1407,8 +1409,7 @@ class PluginWidget(QFrame): | |||
| self.ui.edit_dialog = PluginEdit(self, self.fPluginId) | |||
| self.ui.edit_dialog.hide() | |||
| self.setMinimumHeight(32) | |||
| self.setMaximumHeight(32) | |||
| self.setFixedHeight(32) | |||
| # ------------------------------------------------------------- | |||
| # Set-up connections | |||
| @@ -1643,12 +1644,12 @@ class PluginWidget(QFrame): | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # TESTING | |||
| hasGL = True | |||
| #hasGL = True | |||
| from PyQt5.QtWidgets import QApplication | |||
| app = QApplication(sys.argv) | |||
| #from PyQt5.QtWidgets import QApplication | |||
| #app = QApplication(sys.argv) | |||
| #gui = PluginParameter(None, pInfo, 0, 0) | |||
| #gui = PluginEdit(None, 0) | |||
| gui = PluginWidget(None, 0) | |||
| gui.show() | |||
| app.exec_() | |||
| #gui = PluginWidget(None, 0) | |||
| #gui.show() | |||
| #app.exec_() | |||
| @@ -23,8 +23,6 @@ | |||
| #include "juce_core.h" | |||
| using namespace juce; | |||
| // ----------------------------------------------------------------------- | |||
| static inline | |||
| @@ -34,6 +32,8 @@ const char* find_dssi_ui(const char* const filename, const char* const label) | |||
| CARLA_SAFE_ASSERT_RETURN(label != nullptr, nullptr); | |||
| carla_debug("find_dssi_ui(\"%s\", \"%s\")", filename, label); | |||
| using namespace juce; | |||
| File pluginFile(filename); | |||
| File pluginDir(pluginFile.getParentDirectory().getFullPathName() + File::separatorString + pluginFile.getFileNameWithoutExtension()); | |||