| @@ -25,29 +25,26 @@ from PyQt4.QtGui import QApplication, QListWidget, QListWidgetItem | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Custom Stuff) | |||
| from carla_widgets import * | |||
| from carla_skin import * | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Rack widget item | |||
| class CarlaRackItem(QListWidgetItem): | |||
| kRackItemType = QListWidgetItem.UserType + 1 | |||
| kStaticHeight = 32 | |||
| def __init__(self, parent, pluginId): | |||
| QListWidgetItem.__init__(self, parent, self.kRackItemType) | |||
| self.widget = PluginWidget(parent, pluginId) | |||
| self.widget.setFixedHeight(self.kStaticHeight) | |||
| self.setSizeHint(QSize(300, self.kStaticHeight)) | |||
| self.widget = createPluginSlot(pluginId, parent) | |||
| self.setSizeHint(QSize(300, self.widget.getFixedHeight())) | |||
| parent.setItemWidget(self, self.widget) | |||
| # ----------------------------------------------------------------- | |||
| def close(self): | |||
| self.widget.ui.edit_dialog.close() | |||
| self.widget.fEditDialog.close() | |||
| #def setId(self, idx): | |||
| #self.widget.setId(idx) | |||
| @@ -411,17 +408,7 @@ class CarlaRackW(QListWidget): | |||
| if pitem is None: | |||
| return | |||
| # TODO | |||
| if state == 0: | |||
| pitem.widget.ui.b_gui.setChecked(False) | |||
| pitem.widget.ui.b_gui.setEnabled(True) | |||
| elif state == 1: | |||
| pitem.widget.ui.b_gui.setChecked(True) | |||
| pitem.widget.ui.b_gui.setEnabled(True) | |||
| elif state == -1: | |||
| pitem.widget.ui.b_gui.setChecked(False) | |||
| pitem.widget.ui.b_gui.setEnabled(False) | |||
| pitem.widget.customUiStateChanged(state) | |||
| # ----------------------------------------------------------------- | |||
| @@ -458,7 +445,7 @@ class CarlaRackW(QListWidget): | |||
| if pitem is None: | |||
| return | |||
| pitem.widget.ui.edit_dialog.updateInfo() | |||
| pitem.widget.fEditDialog.updateInfo() | |||
| @pyqtSlot(int) | |||
| def slot_handleReloadInfoCallback(self, pluginId): | |||
| @@ -469,7 +456,7 @@ class CarlaRackW(QListWidget): | |||
| if pitem is None: | |||
| return | |||
| pitem.widget.ui.edit_dialog.reloadInfo() | |||
| pitem.widget.fEditDialog.reloadInfo() | |||
| @pyqtSlot(int) | |||
| def slot_handleReloadParametersCallback(self, pluginId): | |||
| @@ -480,7 +467,7 @@ class CarlaRackW(QListWidget): | |||
| if pitem is None: | |||
| return | |||
| pitem.widget.ui.edit_dialog.reloadParameters() | |||
| pitem.widget.fEditDialog.reloadParameters() | |||
| @pyqtSlot(int) | |||
| def slot_handleReloadProgramsCallback(self, pluginId): | |||
| @@ -491,7 +478,7 @@ class CarlaRackW(QListWidget): | |||
| if pitem is None: | |||
| return | |||
| pitem.widget.ui.edit_dialog.reloadPrograms() | |||
| pitem.widget.fEditDialog.reloadPrograms() | |||
| @pyqtSlot(int) | |||
| def slot_handleReloadAllCallback(self, pluginId): | |||
| @@ -502,6 +489,6 @@ class CarlaRackW(QListWidget): | |||
| if pitem is None: | |||
| return | |||
| pitem.widget.ui.edit_dialog.reloadAll() | |||
| pitem.widget.fEditDialog.reloadAll() | |||
| # ----------------------------------------------------------------- | |||
| @@ -0,0 +1,525 @@ | |||
| #!/usr/bin/env python3 | |||
| # -*- coding: utf-8 -*- | |||
| # Carla plugin/slot skin code | |||
| # Copyright (C) 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) | |||
| from PyQt4.QtCore import pyqtSignal, pyqtSlot | |||
| from PyQt4.QtGui import QFrame | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Custom) | |||
| import ui_carla_plugin | |||
| from carla_widgets import * | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| class PluginSlot(QFrame): | |||
| def __init__(self, parent, pluginId): | |||
| QFrame.__init__(self, parent) | |||
| # ------------------------------------------------------------- | |||
| # Internal stuff | |||
| self.fPluginId = pluginId | |||
| self.fPluginInfo = Carla.host.get_plugin_info(self.fPluginId) if Carla.host is not None else gFakePluginInfo | |||
| self.fPluginInfo['filename'] = charPtrToString(self.fPluginInfo['filename']) | |||
| self.fPluginInfo['name'] = charPtrToString(self.fPluginInfo['name']) | |||
| self.fPluginInfo['label'] = charPtrToString(self.fPluginInfo['label']) | |||
| self.fPluginInfo['maker'] = charPtrToString(self.fPluginInfo['maker']) | |||
| self.fPluginInfo['copyright'] = charPtrToString(self.fPluginInfo['copyright']) | |||
| self.fPluginInfo['iconName'] = charPtrToString(self.fPluginInfo['iconName']) | |||
| self.fParameterIconTimer = ICON_STATE_NULL | |||
| if not Carla.isLocal: | |||
| self.fPluginInfo['hints'] &= ~PLUGIN_HAS_CUSTOM_UI | |||
| if Carla.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK or Carla.host is None: | |||
| self.fPeaksInputCount = 2 | |||
| self.fPeaksOutputCount = 2 | |||
| else: | |||
| audioCountInfo = Carla.host.get_audio_port_count_info(self.fPluginId) | |||
| self.fPeaksInputCount = int(audioCountInfo['ins']) | |||
| self.fPeaksOutputCount = int(audioCountInfo['outs']) | |||
| if self.fPeaksInputCount > 2: | |||
| self.fPeaksInputCount = 2 | |||
| if self.fPeaksOutputCount > 2: | |||
| self.fPeaksOutputCount = 2 | |||
| # ------------------------------------------------------------- | |||
| # Set-up GUI | |||
| self.fEditDialog = PluginEdit(self, self.fPluginId) | |||
| self.fEditDialog.hide() | |||
| #------------------------------------------------------------------ | |||
| def getFixedHeight(self): | |||
| return 32 | |||
| def getHints(self): | |||
| return self.fPluginInfo['hints'] | |||
| #------------------------------------------------------------------ | |||
| def recheckPluginHints(self, hints): | |||
| self.fPluginInfo['hints'] = hints | |||
| def setId(self, idx): | |||
| self.fPluginId = idx | |||
| self.fEditDialog.setId(idx) | |||
| def setName(self, name): | |||
| self.fEditDialog.setName(name) | |||
| #------------------------------------------------------------------ | |||
| def setActive(self, active, sendGui=False, sendCallback=True): | |||
| if sendGui: self.activeChanged(active) | |||
| if sendCallback: Carla.host.set_active(self.fPluginId, active) | |||
| if active: | |||
| self.fEditDialog.clearNotes() | |||
| self.midiActivityChanged(False) | |||
| # called from rack, checks if param is possible first | |||
| def setInternalParameter(self, parameterId, value): | |||
| if parameterId <= PARAMETER_MAX or parameterId >= PARAMETER_NULL: | |||
| return | |||
| if parameterId == PARAMETER_ACTIVE: | |||
| return self.setActive(bool(value), True, True) | |||
| elif parameterId == PARAMETER_DRYWET: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_DRYWET) == 0: return | |||
| Carla.host.set_drywet(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_VOLUME: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_VOLUME) == 0: return | |||
| Carla.host.set_volume(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_BALANCE_LEFT: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_BALANCE) == 0: return | |||
| Carla.host.set_balance_left(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_BALANCE_RIGHT: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_BALANCE) == 0: return | |||
| Carla.host.set_balance_right(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_PANNING: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_PANNING) == 0: return | |||
| Carla.host.set_panning(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_CTRL_CHANNEL: | |||
| Carla.host.set_ctrl_channel(self.fPluginId, value) | |||
| self.fEditDialog.setParameterValue(parameterId, value) | |||
| #------------------------------------------------------------------ | |||
| def setParameterValue(self, parameterId, value): | |||
| self.fParameterIconTimer = ICON_STATE_ON | |||
| if parameterId == PARAMETER_ACTIVE: | |||
| return self.setActive(bool(value), True, False) | |||
| self.fEditDialog.setParameterValue(parameterId, value) | |||
| def setParameterDefault(self, parameterId, value): | |||
| self.fEditDialog.setParameterDefault(parameterId, value) | |||
| def setParameterMidiControl(self, parameterId, control): | |||
| self.fEditDialog.setParameterMidiControl(parameterId, control) | |||
| def setParameterMidiChannel(self, parameterId, channel): | |||
| self.fEditDialog.setParameterMidiChannel(parameterId, channel) | |||
| #------------------------------------------------------------------ | |||
| def setProgram(self, index): | |||
| self.fParameterIconTimer = ICON_STATE_ON | |||
| self.fEditDialog.setProgram(index) | |||
| def setMidiProgram(self, index): | |||
| self.fParameterIconTimer = ICON_STATE_ON | |||
| self.fEditDialog.setMidiProgram(index) | |||
| #------------------------------------------------------------------ | |||
| def sendNoteOn(self, channel, note): | |||
| if self.fEditDialog.sendNoteOn(channel, note): | |||
| self.midiActivityChanged(True) | |||
| def sendNoteOff(self, channel, note): | |||
| if self.fEditDialog.sendNoteOff(channel, note): | |||
| self.midiActivityChanged(False) | |||
| #------------------------------------------------------------------ | |||
| def activeChanged(self, onOff): | |||
| pass | |||
| def editDialogChanged(self, visible): | |||
| pass | |||
| def customUiStateChanged(self, state): | |||
| pass | |||
| def parameterActivityChanged(self, onOff): | |||
| pass | |||
| def midiActivityChanged(self, onOff): | |||
| pass | |||
| #------------------------------------------------------------------ | |||
| def idleFast(self): | |||
| pass | |||
| def idleSlow(self): | |||
| if self.fParameterIconTimer == ICON_STATE_ON: | |||
| self.fParameterIconTimer = ICON_STATE_WAIT | |||
| self.parameterActivityChanged(True) | |||
| elif self.fParameterIconTimer == ICON_STATE_WAIT: | |||
| self.fParameterIconTimer = ICON_STATE_OFF | |||
| elif self.fParameterIconTimer == ICON_STATE_OFF: | |||
| self.fParameterIconTimer = ICON_STATE_NULL | |||
| self.parameterActivityChanged(False) | |||
| self.fEditDialog.idleSlow() | |||
| #------------------------------------------------------------------ | |||
| @pyqtSlot(bool) | |||
| def slot_showCustomUi(self, show): | |||
| Carla.host.show_custom_ui(self.fPluginId, show) | |||
| @pyqtSlot(bool) | |||
| def slot_showEditDialog(self, show): | |||
| self.fEditDialog.setVisible(show) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| class PluginSlot_Default(PluginSlot): | |||
| def __init__(self, parent, pluginId): | |||
| PluginSlot.__init__(self, parent, pluginId) | |||
| self.ui = ui_carla_plugin.Ui_PluginWidget() | |||
| self.ui.setupUi(self) | |||
| # ------------------------------------------------------------- | |||
| # Internal stuff | |||
| self.fLastGreenLedState = False | |||
| self.fLastBlueLedState = False | |||
| if self.palette().window().color().lightness() > 100: | |||
| # Light background | |||
| labelColor = "333" | |||
| isLight = True | |||
| self.fColorTop = QColor(60, 60, 60) | |||
| self.fColorBottom = QColor(47, 47, 47) | |||
| self.fColorSeprtr = QColor(70, 70, 70) | |||
| else: | |||
| # Dark background | |||
| labelColor = "BBB" | |||
| isLight = False | |||
| self.fColorTop = QColor(60, 60, 60) | |||
| self.fColorBottom = QColor(47, 47, 47) | |||
| self.fColorSeprtr = QColor(70, 70, 70) | |||
| # ------------------------------------------------------------- | |||
| # Set-up GUI | |||
| self.setStyleSheet(""" | |||
| QLabel#label_name { | |||
| color: #%s; | |||
| }""" % labelColor) | |||
| if isLight: | |||
| self.ui.b_enable.setPixmaps(":/bitmaps/button_off2.png", ":/bitmaps/button_on2.png", ":/bitmaps/button_off2.png") | |||
| self.ui.b_edit.setPixmaps(":/bitmaps/button_edit2.png", ":/bitmaps/button_edit_down2.png", ":/bitmaps/button_edit_hover2.png") | |||
| if self.fPluginInfo['iconName'] == "distrho": | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_distrho2.png", ":/bitmaps/button_distrho_down2.png", ":/bitmaps/button_distrho_hover2.png") | |||
| elif self.fPluginInfo['iconName'] == "file": | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_file2.png", ":/bitmaps/button_file_down2.png", ":/bitmaps/button_file_hover2.png") | |||
| else: | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_gui2.png", ":/bitmaps/button_gui_down2.png", ":/bitmaps/button_gui_hover2.png") | |||
| else: | |||
| self.ui.b_enable.setPixmaps(":/bitmaps/button_off.png", ":/bitmaps/button_on.png", ":/bitmaps/button_off.png") | |||
| self.ui.b_edit.setPixmaps(":/bitmaps/button_edit.png", ":/bitmaps/button_edit_down.png", ":/bitmaps/button_edit_hover.png") | |||
| if self.fPluginInfo['iconName'] == "distrho": | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_distrho.png", ":/bitmaps/button_distrho_down.png", ":/bitmaps/button_distrho_hover.png") | |||
| elif self.fPluginInfo['iconName'] == "file": | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_file.png", ":/bitmaps/button_file_down.png", ":/bitmaps/button_file_hover.png") | |||
| else: | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_gui.png", ":/bitmaps/button_gui_down.png", ":/bitmaps/button_gui_hover.png") | |||
| self.ui.b_gui.setEnabled((self.fPluginInfo['hints'] & PLUGIN_HAS_CUSTOM_UI) != 0) | |||
| self.ui.led_control.setColor(self.ui.led_control.YELLOW) | |||
| self.ui.led_control.setEnabled(False) | |||
| self.ui.led_midi.setColor(self.ui.led_midi.RED) | |||
| self.ui.led_midi.setEnabled(False) | |||
| self.ui.led_audio_in.setColor(self.ui.led_audio_in.GREEN) | |||
| self.ui.led_audio_in.setEnabled(False) | |||
| self.ui.led_audio_out.setColor(self.ui.led_audio_out.BLUE) | |||
| self.ui.led_audio_out.setEnabled(False) | |||
| self.ui.peak_in.setColor(self.ui.peak_in.GREEN) | |||
| self.ui.peak_in.setChannels(self.fPeaksInputCount) | |||
| self.ui.peak_in.setOrientation(self.ui.peak_in.HORIZONTAL) | |||
| self.ui.peak_out.setColor(self.ui.peak_in.BLUE) | |||
| self.ui.peak_out.setChannels(self.fPeaksOutputCount) | |||
| self.ui.peak_out.setOrientation(self.ui.peak_out.HORIZONTAL) | |||
| self.ui.label_name.setText(self.fPluginInfo['name']) | |||
| self.setFixedHeight(32) | |||
| # ------------------------------------------------------------- | |||
| # Set-up connections | |||
| self.ui.b_enable.clicked.connect(self.slot_enableClicked) | |||
| self.ui.b_gui.clicked.connect(self.slot_showCustomUi) | |||
| self.ui.b_edit.clicked.connect(self.slot_showEditDialog) | |||
| self.customContextMenuRequested.connect(self.slot_showCustomMenu) | |||
| #------------------------------------------------------------------ | |||
| def getFixedHeight(self): | |||
| return 32 | |||
| #------------------------------------------------------------------ | |||
| def recheckPluginHints(self, hints): | |||
| self.ui.b_gui.setEnabled(hints & PLUGIN_HAS_CUSTOM_UI) | |||
| PluginSlot.recheckPluginHints(self, hints) | |||
| def setName(self, name): | |||
| self.ui.label_name.setText(name) | |||
| PluginSlot.setName(self, name) | |||
| #------------------------------------------------------------------ | |||
| def activeChanged(self, onOff): | |||
| self.ui.b_enable.setChecked(onOff) | |||
| def editDialogChanged(self, visible): | |||
| self.ui.b_edit.blockSignals(True) | |||
| self.ui.b_edit.setChecked(visible) | |||
| self.ui.b_edit.blockSignals(False) | |||
| def customUiStateChanged(self, state): | |||
| self.ui.b_gui.blockSignals(True) | |||
| if state == 0: | |||
| self.ui.b_gui.setChecked(False) | |||
| self.ui.b_gui.setEnabled(True) | |||
| elif state == 1: | |||
| self.ui.b_gui.setChecked(True) | |||
| self.ui.b_gui.setEnabled(True) | |||
| elif state == -1: | |||
| self.ui.b_gui.setChecked(False) | |||
| self.ui.b_gui.setEnabled(False) | |||
| self.ui.b_gui.blockSignals(False) | |||
| def parameterActivityChanged(self, onOff): | |||
| self.ui.led_control.setChecked(onOff) | |||
| def midiActivityChanged(self, onOff): | |||
| self.ui.led_midi.setChecked(onOff) | |||
| #------------------------------------------------------------------ | |||
| def idleFast(self): | |||
| # Input peaks | |||
| if self.fPeaksInputCount > 0: | |||
| if self.fPeaksInputCount > 1: | |||
| peak1 = Carla.host.get_input_peak_value(self.fPluginId, 1) | |||
| peak2 = Carla.host.get_input_peak_value(self.fPluginId, 2) | |||
| ledState = bool(peak1 != 0.0 or peak2 != 0.0) | |||
| self.ui.peak_in.displayMeter(1, peak1) | |||
| self.ui.peak_in.displayMeter(2, peak2) | |||
| else: | |||
| peak = Carla.host.get_input_peak_value(self.fPluginId, 1) | |||
| ledState = bool(peak != 0.0) | |||
| self.ui.peak_in.displayMeter(1, peak) | |||
| if self.fLastGreenLedState != ledState: | |||
| self.fLastGreenLedState = ledState | |||
| self.ui.led_audio_in.setChecked(ledState) | |||
| # Output peaks | |||
| if self.fPeaksOutputCount > 0: | |||
| if self.fPeaksOutputCount > 1: | |||
| peak1 = Carla.host.get_output_peak_value(self.fPluginId, 1) | |||
| peak2 = Carla.host.get_output_peak_value(self.fPluginId, 2) | |||
| ledState = bool(peak1 != 0.0 or peak2 != 0.0) | |||
| self.ui.peak_out.displayMeter(1, peak1) | |||
| self.ui.peak_out.displayMeter(2, peak2) | |||
| else: | |||
| peak = Carla.host.get_output_peak_value(self.fPluginId, 1) | |||
| ledState = bool(peak != 0.0) | |||
| self.ui.peak_out.displayMeter(1, peak) | |||
| if self.fLastBlueLedState != ledState: | |||
| self.fLastBlueLedState = ledState | |||
| self.ui.led_audio_out.setChecked(ledState) | |||
| #------------------------------------------------------------------ | |||
| @pyqtSlot(bool) | |||
| def slot_enableClicked(self, yesNo): | |||
| self.setActive(yesNo, False, True) | |||
| @pyqtSlot() | |||
| def slot_showCustomMenu(self): | |||
| menu = QMenu(self) | |||
| actActive = menu.addAction(self.tr("Disable") if self.fIsEnabled else self.tr("Enable")) | |||
| menu.addSeparator() | |||
| actGui = menu.addAction(self.tr("Show GUI")) | |||
| actGui.setCheckable(True) | |||
| actGui.setChecked(self.ui.b_gui.isChecked()) | |||
| actGui.setEnabled(self.ui.b_gui.isEnabled()) | |||
| actEdit = menu.addAction(self.tr("Edit")) | |||
| actEdit.setCheckable(True) | |||
| actEdit.setChecked(self.ui.b_edit.isChecked()) | |||
| menu.addSeparator() | |||
| actClone = menu.addAction(self.tr("Clone")) | |||
| actRename = menu.addAction(self.tr("Rename...")) | |||
| actRemove = menu.addAction(self.tr("Remove")) | |||
| actSel = menu.exec_(QCursor.pos()) | |||
| if not actSel: | |||
| return | |||
| if actSel == actActive: | |||
| self.setActive(not self.ui.b_enable.isChecked(), True, True) | |||
| elif actSel == actGui: | |||
| self.ui.b_gui.click() | |||
| elif actSel == actEdit: | |||
| self.ui.b_edit.click() | |||
| elif actSel == actClone: | |||
| if not Carla.host.clone_plugin(self.fPluginId): | |||
| CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | |||
| Carla.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) | |||
| elif actSel == actRename: | |||
| oldName = self.fPluginInfo['name'] | |||
| newNameTry = QInputDialog.getText(self, self.tr("Rename Plugin"), self.tr("New plugin name:"), QLineEdit.Normal, oldName) | |||
| if not (newNameTry[1] and newNameTry[0] and oldName != newNameTry[0]): | |||
| return | |||
| newName = newNameTry[0] | |||
| if Carla.host is None or Carla.host.rename_plugin(self.fPluginId, newName): | |||
| self.setName(newName) | |||
| else: | |||
| CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | |||
| Carla.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) | |||
| elif actSel == actRemove: | |||
| if not Carla.host.remove_plugin(self.fPluginId): | |||
| CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | |||
| Carla.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) | |||
| #------------------------------------------------------------------ | |||
| def paintEvent(self, event): | |||
| painter = QPainter(self) | |||
| painter.save() | |||
| areaX = self.ui.area_right.x()+7 | |||
| painter.setPen(self.fColorSeprtr.lighter(110)) | |||
| painter.setBrush(self.fColorBottom) | |||
| painter.setRenderHint(QPainter.Antialiasing, True) | |||
| # name -> leds arc | |||
| path = QPainterPath() | |||
| path.moveTo(areaX-20, self.height()-4) | |||
| path.cubicTo(areaX, self.height()-5, areaX-20, 4.75, areaX, 4.75) | |||
| path.lineTo(areaX, self.height()-5) | |||
| painter.drawPath(path) | |||
| painter.setPen(self.fColorSeprtr) | |||
| painter.setRenderHint(QPainter.Antialiasing, False) | |||
| # separator lines | |||
| painter.drawLine(0, self.height()-5, areaX-20, self.height()-5) | |||
| painter.drawLine(areaX, 4, self.width(), 4) | |||
| painter.setPen(self.fColorBottom) | |||
| painter.setBrush(self.fColorBottom) | |||
| # top, bottom and left lines | |||
| painter.drawLine(0, 0, self.width(), 0) | |||
| painter.drawRect(0, self.height()-4, areaX, 4) | |||
| painter.drawRoundedRect(areaX-20, self.height()-5, areaX, 5, 22, 22) | |||
| painter.drawLine(0, 0, 0, self.height()) | |||
| # fill the rest | |||
| painter.drawRect(areaX-1, 5, self.width(), self.height()) | |||
| # bottom 1px line | |||
| painter.setPen(self.fColorSeprtr) | |||
| painter.drawLine(0, self.height()-1, self.width(), self.height()-1) | |||
| painter.restore() | |||
| PluginSlot.paintEvent(self, event) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| def createPluginSlot(pluginId, parent): | |||
| pluginInfo = Carla.host.get_plugin_info(pluginId) | |||
| pluginInfo['label'] = charPtrToString(pluginInfo['label']) | |||
| pluginInfo['maker'] = charPtrToString(pluginInfo['maker']) | |||
| pluginInfo['iconName'] = charPtrToString(pluginInfo['iconName']) | |||
| return PluginSlot_Default(parent, pluginId) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| @@ -29,7 +29,6 @@ from PyQt4.QtGui import QDialog, QFrame, QInputDialog, QLineEdit, QMenu, QVBoxLa | |||
| import ui_carla_about | |||
| import ui_carla_edit | |||
| import ui_carla_parameter | |||
| import ui_carla_plugin | |||
| from carla_shared import * | |||
| @@ -386,7 +385,8 @@ class PluginEdit(QDialog): | |||
| self.fCurrentProgram = -1 | |||
| self.fCurrentMidiProgram = -1 | |||
| self.fCurrentStateFilename = None | |||
| self.fControlChannel = 0 | |||
| self.fControlChannel = 0 | |||
| self.fFirstInit = True | |||
| self.fScrollAreaSetup = False | |||
| self.fParameterCount = 0 | |||
| @@ -529,6 +529,8 @@ class PluginEdit(QDialog): | |||
| if not self.ui.scrollArea.isEnabled(): | |||
| self.resize(self.width(), self.height()-self.ui.scrollArea.height()) | |||
| self.fFirstInit = False | |||
| #------------------------------------------------------------------ | |||
| def reloadInfo(self): | |||
| @@ -661,7 +663,7 @@ class PluginEdit(QDialog): | |||
| self.ui.scrollArea.setVisible(showKeyboard) | |||
| # Force-Update parent for new hints | |||
| if self.fRealParent: | |||
| if self.fRealParent and not self.fFirstInit: | |||
| self.fRealParent.recheckPluginHints(pluginHints) | |||
| def reloadParameters(self): | |||
| @@ -893,6 +895,7 @@ class PluginEdit(QDialog): | |||
| self.fPluginId = idx | |||
| def setName(self, name): | |||
| self.fPluginInfo['name'] = name | |||
| self.ui.label_plugin.setText("\n%s\n" % name) | |||
| self.setWindowTitle(name) | |||
| @@ -1214,7 +1217,7 @@ class PluginEdit(QDialog): | |||
| @pyqtSlot() | |||
| def slot_finished(self): | |||
| if self.fRealParent is not None: | |||
| self.fRealParent.editClosed() | |||
| self.fRealParent.editDialogChanged(False) | |||
| #------------------------------------------------------------------ | |||
| @@ -1394,412 +1397,6 @@ class PluginEdit(QDialog): | |||
| QDialog.done(self, r) | |||
| self.close() | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Plugin Widget | |||
| class PluginWidget(QFrame): | |||
| def __init__(self, parent, pluginId): | |||
| QFrame.__init__(self, parent) | |||
| self.ui = ui_carla_plugin.Ui_PluginWidget() | |||
| self.ui.setupUi(self) | |||
| # ------------------------------------------------------------- | |||
| # Internal stuff | |||
| self.fPluginId = pluginId | |||
| self.fPluginInfo = Carla.host.get_plugin_info(self.fPluginId) if Carla.host is not None else gFakePluginInfo | |||
| self.fPluginInfo['filename'] = charPtrToString(self.fPluginInfo['filename']) | |||
| self.fPluginInfo['name'] = charPtrToString(self.fPluginInfo['name']) | |||
| self.fPluginInfo['label'] = charPtrToString(self.fPluginInfo['label']) | |||
| self.fPluginInfo['maker'] = charPtrToString(self.fPluginInfo['maker']) | |||
| self.fPluginInfo['copyright'] = charPtrToString(self.fPluginInfo['copyright']) | |||
| self.fPluginInfo['iconName'] = charPtrToString(self.fPluginInfo['iconName']) | |||
| if not Carla.isLocal: | |||
| self.fPluginInfo['hints'] &= ~PLUGIN_HAS_CUSTOM_UI | |||
| self.fLastGreenLedState = False | |||
| self.fLastBlueLedState = False | |||
| self.fParameterIconTimer = ICON_STATE_NULL | |||
| if Carla.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK or Carla.host is None: | |||
| self.fPeaksInputCount = 2 | |||
| self.fPeaksOutputCount = 2 | |||
| else: | |||
| audioCountInfo = Carla.host.get_audio_port_count_info(self.fPluginId) | |||
| self.fPeaksInputCount = int(audioCountInfo['ins']) | |||
| self.fPeaksOutputCount = int(audioCountInfo['outs']) | |||
| if self.fPeaksInputCount > 2: | |||
| self.fPeaksInputCount = 2 | |||
| if self.fPeaksOutputCount > 2: | |||
| self.fPeaksOutputCount = 2 | |||
| if self.palette().window().color().lightness() > 100: | |||
| # Light background | |||
| labelColor = "333" | |||
| isLight = True | |||
| self.fColorTop = QColor(60, 60, 60) | |||
| self.fColorBottom = QColor(47, 47, 47) | |||
| self.fColorSeprtr = QColor(70, 70, 70) | |||
| else: | |||
| # Dark background | |||
| labelColor = "BBB" | |||
| isLight = False | |||
| self.fColorTop = QColor(60, 60, 60) | |||
| self.fColorBottom = QColor(47, 47, 47) | |||
| self.fColorSeprtr = QColor(70, 70, 70) | |||
| # ------------------------------------------------------------- | |||
| # Set-up GUI | |||
| self.setStyleSheet(""" | |||
| QLabel#label_name { | |||
| color: #%s; | |||
| }""" % labelColor) | |||
| if isLight: | |||
| self.ui.b_enable.setPixmaps(":/bitmaps/button_off2.png", ":/bitmaps/button_on2.png", ":/bitmaps/button_off2.png") | |||
| self.ui.b_edit.setPixmaps(":/bitmaps/button_edit2.png", ":/bitmaps/button_edit_down2.png", ":/bitmaps/button_edit_hover2.png") | |||
| if self.fPluginInfo['iconName'] == "distrho": | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_distrho2.png", ":/bitmaps/button_distrho_down2.png", ":/bitmaps/button_distrho_hover2.png") | |||
| elif self.fPluginInfo['iconName'] == "file": | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_file2.png", ":/bitmaps/button_file_down2.png", ":/bitmaps/button_file_hover2.png") | |||
| else: | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_gui2.png", ":/bitmaps/button_gui_down2.png", ":/bitmaps/button_gui_hover2.png") | |||
| else: | |||
| self.ui.b_enable.setPixmaps(":/bitmaps/button_off.png", ":/bitmaps/button_on.png", ":/bitmaps/button_off.png") | |||
| self.ui.b_edit.setPixmaps(":/bitmaps/button_edit.png", ":/bitmaps/button_edit_down.png", ":/bitmaps/button_edit_hover.png") | |||
| if self.fPluginInfo['iconName'] == "distrho": | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_distrho.png", ":/bitmaps/button_distrho_down.png", ":/bitmaps/button_distrho_hover.png") | |||
| elif self.fPluginInfo['iconName'] == "file": | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_file.png", ":/bitmaps/button_file_down.png", ":/bitmaps/button_file_hover.png") | |||
| else: | |||
| self.ui.b_gui.setPixmaps(":/bitmaps/button_gui.png", ":/bitmaps/button_gui_down.png", ":/bitmaps/button_gui_hover.png") | |||
| self.ui.led_control.setColor(self.ui.led_control.YELLOW) | |||
| self.ui.led_control.setEnabled(False) | |||
| self.ui.led_midi.setColor(self.ui.led_midi.RED) | |||
| self.ui.led_midi.setEnabled(False) | |||
| self.ui.led_audio_in.setColor(self.ui.led_audio_in.GREEN) | |||
| self.ui.led_audio_in.setEnabled(False) | |||
| self.ui.led_audio_out.setColor(self.ui.led_audio_out.BLUE) | |||
| self.ui.led_audio_out.setEnabled(False) | |||
| self.ui.peak_in.setColor(self.ui.peak_in.GREEN) | |||
| self.ui.peak_in.setChannels(self.fPeaksInputCount) | |||
| self.ui.peak_in.setOrientation(self.ui.peak_in.HORIZONTAL) | |||
| self.ui.peak_out.setColor(self.ui.peak_in.BLUE) | |||
| self.ui.peak_out.setChannels(self.fPeaksOutputCount) | |||
| self.ui.peak_out.setOrientation(self.ui.peak_out.HORIZONTAL) | |||
| self.ui.label_name.setText(self.fPluginInfo['name']) | |||
| self.ui.edit_dialog = PluginEdit(self, self.fPluginId) | |||
| self.ui.edit_dialog.hide() | |||
| self.setFixedHeight(32) | |||
| # ------------------------------------------------------------- | |||
| # Set-up connections | |||
| self.customContextMenuRequested.connect(self.slot_showCustomMenu) | |||
| self.ui.b_enable.clicked.connect(self.slot_enableClicked) | |||
| self.ui.b_gui.clicked.connect(self.slot_guiClicked) | |||
| self.ui.b_edit.clicked.connect(self.slot_editClicked) | |||
| #------------------------------------------------------------------ | |||
| def idleFast(self): | |||
| # Input peaks | |||
| if self.fPeaksInputCount > 0: | |||
| if self.fPeaksInputCount > 1: | |||
| peak1 = Carla.host.get_input_peak_value(self.fPluginId, 1) | |||
| peak2 = Carla.host.get_input_peak_value(self.fPluginId, 2) | |||
| ledState = bool(peak1 != 0.0 or peak2 != 0.0) | |||
| self.ui.peak_in.displayMeter(1, peak1) | |||
| self.ui.peak_in.displayMeter(2, peak2) | |||
| else: | |||
| peak = Carla.host.get_input_peak_value(self.fPluginId, 1) | |||
| ledState = bool(peak != 0.0) | |||
| self.ui.peak_in.displayMeter(1, peak) | |||
| if self.fLastGreenLedState != ledState: | |||
| self.fLastGreenLedState = ledState | |||
| self.ui.led_audio_in.setChecked(ledState) | |||
| # Output peaks | |||
| if self.fPeaksOutputCount > 0: | |||
| if self.fPeaksOutputCount > 1: | |||
| peak1 = Carla.host.get_output_peak_value(self.fPluginId, 1) | |||
| peak2 = Carla.host.get_output_peak_value(self.fPluginId, 2) | |||
| ledState = bool(peak1 != 0.0 or peak2 != 0.0) | |||
| self.ui.peak_out.displayMeter(1, peak1) | |||
| self.ui.peak_out.displayMeter(2, peak2) | |||
| else: | |||
| peak = Carla.host.get_output_peak_value(self.fPluginId, 1) | |||
| ledState = bool(peak != 0.0) | |||
| self.ui.peak_out.displayMeter(1, peak) | |||
| if self.fLastBlueLedState != ledState: | |||
| self.fLastBlueLedState = ledState | |||
| self.ui.led_audio_out.setChecked(ledState) | |||
| def idleSlow(self): | |||
| # Parameter Activity LED | |||
| if self.fParameterIconTimer == ICON_STATE_ON: | |||
| self.fParameterIconTimer = ICON_STATE_WAIT | |||
| self.ui.led_control.setChecked(True) | |||
| elif self.fParameterIconTimer == ICON_STATE_WAIT: | |||
| self.fParameterIconTimer = ICON_STATE_OFF | |||
| elif self.fParameterIconTimer == ICON_STATE_OFF: | |||
| self.fParameterIconTimer = ICON_STATE_NULL | |||
| self.ui.led_control.setChecked(False) | |||
| # Update edit dialog | |||
| self.ui.edit_dialog.idleSlow() | |||
| #------------------------------------------------------------------ | |||
| def editClosed(self): | |||
| self.ui.b_edit.setChecked(False) | |||
| def recheckPluginHints(self, hints): | |||
| self.fPluginInfo['hints'] = hints | |||
| self.ui.b_gui.setEnabled(hints & PLUGIN_HAS_CUSTOM_UI) | |||
| #------------------------------------------------------------------ | |||
| def getHints(self): | |||
| return self.fPluginInfo['hints'] | |||
| def setId(self, idx): | |||
| self.fPluginId = idx | |||
| self.ui.edit_dialog.setId(idx) | |||
| def setName(self, name): | |||
| self.ui.label_name.setText(name) | |||
| self.ui.edit_dialog.setName(name) | |||
| #------------------------------------------------------------------ | |||
| def setActive(self, active, sendGui=False, sendCallback=True): | |||
| if sendGui: self.ui.b_enable.setChecked(active) | |||
| if sendCallback: Carla.host.set_active(self.fPluginId, active) | |||
| if active: | |||
| self.ui.edit_dialog.clearNotes() | |||
| self.ui.led_midi.setChecked(False) | |||
| # called from rack, checks if param is possible first | |||
| def setInternalParameter(self, parameterId, value): | |||
| if parameterId <= PARAMETER_MAX or parameterId >= PARAMETER_NULL: | |||
| return | |||
| if parameterId == PARAMETER_ACTIVE: | |||
| return self.setActive(bool(value), True, True) | |||
| elif parameterId == PARAMETER_DRYWET: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_DRYWET) == 0: return | |||
| Carla.host.set_drywet(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_VOLUME: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_VOLUME) == 0: return | |||
| Carla.host.set_volume(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_BALANCE_LEFT: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_BALANCE) == 0: return | |||
| Carla.host.set_balance_left(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_BALANCE_RIGHT: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_BALANCE) == 0: return | |||
| Carla.host.set_balance_right(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_PANNING: | |||
| if (self.fPluginInfo['hints'] & PLUGIN_CAN_PANNING) == 0: return | |||
| Carla.host.set_panning(self.fPluginId, value) | |||
| elif parameterId == PARAMETER_CTRL_CHANNEL: | |||
| Carla.host.set_ctrl_channel(self.fPluginId, value) | |||
| self.ui.edit_dialog.setParameterValue(parameterId, value) | |||
| def setParameterValue(self, parameterId, value): | |||
| self.fParameterIconTimer = ICON_STATE_ON | |||
| if parameterId == PARAMETER_ACTIVE: | |||
| return self.setActive(bool(value), True, False) | |||
| 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) | |||
| def setParameterMidiChannel(self, parameterId, channel): | |||
| self.ui.edit_dialog.setParameterMidiChannel(parameterId, channel) | |||
| def setProgram(self, index): | |||
| self.fParameterIconTimer = ICON_STATE_ON | |||
| self.ui.edit_dialog.setProgram(index) | |||
| def setMidiProgram(self, index): | |||
| self.fParameterIconTimer = ICON_STATE_ON | |||
| self.ui.edit_dialog.setMidiProgram(index) | |||
| #------------------------------------------------------------------ | |||
| def sendNoteOn(self, channel, note): | |||
| if self.ui.edit_dialog.sendNoteOn(channel, note): | |||
| self.ui.led_midi.setChecked(True) | |||
| def sendNoteOff(self, channel, note): | |||
| if self.ui.edit_dialog.sendNoteOff(channel, note): | |||
| self.ui.led_midi.setChecked(False) | |||
| #------------------------------------------------------------------ | |||
| @pyqtSlot() | |||
| def slot_showCustomMenu(self): | |||
| menu = QMenu(self) | |||
| actActive = menu.addAction(self.tr("Disable") if self.ui.b_enable.isChecked() else self.tr("Enable")) | |||
| menu.addSeparator() | |||
| actGui = menu.addAction(self.tr("Show GUI")) | |||
| actGui.setCheckable(True) | |||
| actGui.setChecked(self.ui.b_gui.isChecked()) | |||
| actGui.setEnabled(self.ui.b_gui.isEnabled()) | |||
| actEdit = menu.addAction(self.tr("Edit")) | |||
| actEdit.setCheckable(True) | |||
| actEdit.setChecked(self.ui.b_edit.isChecked()) | |||
| menu.addSeparator() | |||
| actClone = menu.addAction(self.tr("Clone")) | |||
| actRename = menu.addAction(self.tr("Rename...")) | |||
| actRemove = menu.addAction(self.tr("Remove")) | |||
| actSel = menu.exec_(QCursor.pos()) | |||
| if not actSel: | |||
| return | |||
| if actSel == actActive: | |||
| self.setActive(not self.ui.b_enable.isChecked(), True, True) | |||
| elif actSel == actGui: | |||
| self.ui.b_gui.click() | |||
| elif actSel == actEdit: | |||
| self.ui.b_edit.click() | |||
| elif actSel == actClone: | |||
| if not Carla.host.clone_plugin(self.fPluginId): | |||
| CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | |||
| Carla.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) | |||
| elif actSel == actRename: | |||
| oldName = self.fPluginInfo['name'] | |||
| newNameTry = QInputDialog.getText(self, self.tr("Rename Plugin"), self.tr("New plugin name:"), QLineEdit.Normal, oldName) | |||
| if not (newNameTry[1] and newNameTry[0] and oldName != newNameTry[0]): | |||
| return | |||
| newName = newNameTry[0] | |||
| if Carla.host is None or Carla.host.rename_plugin(self.fPluginId, newName): | |||
| self.fPluginInfo['name'] = newName | |||
| self.ui.edit_dialog.fPluginInfo['name'] = newName | |||
| self.ui.edit_dialog.reloadInfo() | |||
| self.ui.label_name.setText(newName) | |||
| else: | |||
| CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | |||
| Carla.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) | |||
| elif actSel == actRemove: | |||
| if not Carla.host.remove_plugin(self.fPluginId): | |||
| CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | |||
| Carla.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) | |||
| #------------------------------------------------------------------ | |||
| @pyqtSlot(bool) | |||
| def slot_enableClicked(self, yesNo): | |||
| self.setActive(yesNo, False, True) | |||
| @pyqtSlot(bool) | |||
| def slot_guiClicked(self, show): | |||
| Carla.host.show_custom_ui(self.fPluginId, show) | |||
| @pyqtSlot(bool) | |||
| def slot_editClicked(self, show): | |||
| self.ui.edit_dialog.setVisible(show) | |||
| #------------------------------------------------------------------ | |||
| def paintEvent(self, event): | |||
| painter = QPainter(self) | |||
| painter.save() | |||
| areaX = self.ui.area_right.x()+7 | |||
| painter.setPen(self.fColorSeprtr.lighter(110)) | |||
| painter.setBrush(self.fColorBottom) | |||
| painter.setRenderHint(QPainter.Antialiasing, True) | |||
| # name -> leds arc | |||
| path = QPainterPath() | |||
| path.moveTo(areaX-20, self.height()-4) | |||
| path.cubicTo(areaX, self.height()-5, areaX-20, 4.75, areaX, 4.75) | |||
| path.lineTo(areaX, self.height()-5) | |||
| painter.drawPath(path) | |||
| painter.setPen(self.fColorSeprtr) | |||
| painter.setRenderHint(QPainter.Antialiasing, False) | |||
| # separator lines | |||
| painter.drawLine(0, self.height()-5, areaX-20, self.height()-5) | |||
| painter.drawLine(areaX, 4, self.width(), 4) | |||
| painter.setPen(self.fColorBottom) | |||
| painter.setBrush(self.fColorBottom) | |||
| # top, bottom and left lines | |||
| painter.drawLine(0, 0, self.width(), 0) | |||
| painter.drawRect(0, self.height()-4, areaX, 4) | |||
| painter.drawRoundedRect(areaX-20, self.height()-5, areaX, 5, 22, 22) | |||
| painter.drawLine(0, 0, 0, self.height()) | |||
| # fill the rest | |||
| painter.drawRect(areaX-1, 5, self.width(), self.height()) | |||
| # bottom 1px line | |||
| painter.setPen(self.fColorSeprtr) | |||
| painter.drawLine(0, self.height()-1, self.width(), self.height()-1) | |||
| painter.restore() | |||
| QFrame.paintEvent(self, event) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Main | |||
| @@ -1811,7 +1408,6 @@ if __name__ == '__main__': | |||
| #gui = CarlaAboutW(None) | |||
| #gui = PluginParameter(None, gFakeParamInfo, 0, 0) | |||
| gui = PluginEdit(None, 0) | |||
| #gui = PluginWidget(None, 0) | |||
| gui.show() | |||
| sys.exit(app.exec_()) | |||