2 # -*- coding: utf-8 -*-
4 # Carla plugin/slot skin code
5 # Copyright (C) 2013-2020 Filipe Coelho <falktx@falktx.com>
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License as
9 # published by the Free Software Foundation; either version 2 of
10 # the License, or any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # For a full copy of the GNU General Public License see the doc/GPL.txt file.
19 # ------------------------------------------------------------------------------------------------------------
22 from PyQt5
.QtCore
import Qt
, QRectF
, QLineF
, QTimer
23 from PyQt5
.QtGui
import QColor
, QFont
, QFontDatabase
, QPainter
, QPainterPath
, QPen
24 from PyQt5
.QtWidgets
import QColorDialog
, QFrame
, QLineEdit
, QPushButton
26 # ------------------------------------------------------------------------------------------------------------
29 import ui_carla_plugin_calf
30 import ui_carla_plugin_classic
31 import ui_carla_plugin_compact
32 import ui_carla_plugin_default
33 import ui_carla_plugin_presets
35 from carla_backend
import *
36 from carla_shared
import *
37 from carla_widgets
import *
38 from widgets
.digitalpeakmeter
import DigitalPeakMeter
39 from widgets
.paramspinbox
import CustomInputDialog
40 from widgets
.scalabledial
import ScalableDial
42 # ------------------------------------------------------------------------------------------------------------
43 # Plugin Skin Rules (WORK IN PROGRESS)
45 # Base is a QFrame (NoFrame, Plain, 0-size lines), with "PluginWidget" as object name.
46 # Spacing of the top-most layout must be 1px.
47 # Top and bottom margins must be 3px (can be split between different Qt layouts).
48 # Left and right margins must be 6px (can be split between different Qt layouts).
49 # If the left or right side has built-in margins, say a transparent svg border,
50 # those margins must be taken into consideration.
52 # There's a top and bottom layout, separated by a horizontal line.
53 # Compacted skins do not have the bottom layout and separating line.
57 # -----------------------------------------------------------------
58 # | <> | <> [ WIDGETS ] [ LEDS ] |
59 # | BUTTONS <> | <> PLUGIN NAME < spacer > [ WIDGETS ] [ LEDS ] |
60 # | <> | <> [ WIDGETS ] [ LEDS ] |
61 # -----------------------------------------------------------------
63 # Buttons area has size fixed. (TBA)
64 # Spacers at the left of the plugin name must be 8x1 in size (fixed).
65 # The line before the plugin name must be height-10px (fixed).
66 # WIDGETS area can be extended to the left, if using meters they should have 80px.
67 # WIDGETS margins are 4px for left+right and 2px for top+bottom, with 4px spacing.
69 # ------------------------------------------------------------------------------------------------------------
70 # Try to "shortify" a parameter name
72 def getParameterShortName(paramName
):
73 paramName
= paramName
.split("/",1)[0].split(" (",1)[0].split(" [",1)[0].strip()
74 paramLow
= paramName
.lower()
77 if paramLow
.startswith("compressor "):
78 paramName
= paramName
.replace("ompressor ", ".", 1)
79 paramLow
= paramName
.lower()
80 elif paramLow
.startswith("room "):
81 paramName
= paramName
.split(" ",1)[1]
82 paramLow
= paramName
.lower()
85 if paramLow
.endswith(" level"):
86 paramName
= paramName
.rsplit(" ",1)[0]
87 paramLow
= paramName
.lower()
88 elif paramLow
.endswith(" time"):
89 paramName
= paramName
.rsplit(" ",1)[0]
90 paramLow
= paramName
.lower()
93 if "attack" in paramLow
:
94 paramName
= paramName
.replace("ttack", "tk")
95 elif "bandwidth" in paramLow
:
96 paramName
= paramName
.replace("andwidth", "w")
97 elif "damping" in paramLow
:
98 paramName
= paramName
.replace("amping", "amp")
99 elif "distortion" in paramLow
:
100 paramName
= paramName
.replace("istortion", "ist")
101 elif "feedback" in paramLow
:
102 paramName
= paramName
.replace("eedback", "b")
103 elif "frequency" in paramLow
:
104 paramName
= paramName
.replace("requency", "req")
105 elif "input" in paramLow
:
106 paramName
= paramName
.replace("nput", "n")
107 elif "makeup" in paramLow
:
108 paramName
= paramName
.replace("akeup", "kUp" if "Make" in paramName
else "kup")
109 elif "output" in paramLow
:
110 paramName
= paramName
.replace("utput", "ut")
111 elif "random" in paramLow
:
112 paramName
= paramName
.replace("andom", "nd")
113 elif "threshold" in paramLow
:
114 paramName
= paramName
.replace("hreshold", "hres")
116 # remove space if last char from 1st word is lowercase and the first char from the 2nd is uppercase,
117 # or if 2nd is a number
119 name1
, name2
= paramName
.split(" ", 1)
120 if (name1
[-1].islower() and name2
[0].isupper()) or name2
.isdigit():
121 paramName
= paramName
.replace(" ", "", 1)
123 # cut stuff if too big
124 if len(paramName
) > 7:
125 paramName
= paramName
.replace("a","").replace("e","").replace("i","").replace("o","").replace("u","")
127 if len(paramName
) > 7:
128 paramName
= paramName
[:7]
130 return paramName
.strip()
132 # ------------------------------------------------------------------------------------------------------------
133 # Get RGB colors for a plugin category
135 def getColorFromCategory(category
):
140 if category
== PLUGIN_CATEGORY_MODULATOR
:
142 elif category
== PLUGIN_CATEGORY_EQ
:
144 elif category
== PLUGIN_CATEGORY_FILTER
:
146 elif category
== PLUGIN_CATEGORY_DELAY
:
149 elif category
== PLUGIN_CATEGORY_DISTORTION
:
152 elif category
== PLUGIN_CATEGORY_DYNAMICS
:
155 elif category
== PLUGIN_CATEGORY_UTILITY
:
161 # ------------------------------------------------------------------------------------------------------------
164 def setScalableDialStyle(widget
, parameterId
, parameterCount
, whiteLabels
, skinStyle
):
165 if skinStyle
.startswith("calf"):
166 widget
.setCustomPaintMode(ScalableDial
.CUSTOM_PAINT_MODE_NO_GRADIENT
)
169 elif skinStyle
.startswith("openav"):
170 widget
.setCustomPaintMode(ScalableDial
.CUSTOM_PAINT_MODE_NO_GRADIENT
)
171 if parameterId
== PARAMETER_DRYWET
:
173 elif parameterId
== PARAMETER_VOLUME
:
179 if parameterId
== PARAMETER_DRYWET
:
180 widget
.setCustomPaintMode(ScalableDial
.CUSTOM_PAINT_MODE_CARLA_WET
)
182 elif parameterId
== PARAMETER_VOLUME
:
183 widget
.setCustomPaintMode(ScalableDial
.CUSTOM_PAINT_MODE_CARLA_VOL
)
186 _r
= 255 - int((float(parameterId
)/float(parameterCount
))*200.0)
187 _g
= 55 + int((float(parameterId
)/float(parameterCount
))*200.0)
189 widget
.setCustomPaintColor(QColor(_r
, _g
, _b
))
190 widget
.setCustomPaintMode(ScalableDial
.CUSTOM_PAINT_MODE_COLOR
)
193 colorEnabled
= QColor("#BBB")
194 colorDisabled
= QColor("#555")
196 colorEnabled
= QColor("#111")
197 colorDisabled
= QColor("#AAA")
199 widget
.setLabelColor(colorEnabled
, colorDisabled
)
202 # ------------------------------------------------------------------------------------------------------------
203 # Abstract plugin slot
205 class AbstractPluginSlot(QFrame
, PluginEditParentMeta
):
206 def __init__(self
, parent
, host
, pluginId
, skinColor
, skinStyle
):
207 QFrame
.__init
__(self
, parent
)
209 self
.fParent
= parent
211 # -------------------------------------------------------------
214 self
.fPluginId
= pluginId
215 self
.fPluginInfo
= host
.get_plugin_info(self
.fPluginId
)
216 self
.fSkinColor
= skinColor
217 self
.fSkinStyle
= skinStyle
218 self
.fDarkStyle
= QColor(skinColor
[0], skinColor
[1], skinColor
[2]).blackF() > 0.4
220 # -------------------------------------------------------------
223 self
.fIsActive
= False
224 self
.fIsSelected
= False
226 self
.fLastGreenLedState
= False
227 self
.fLastBlueLedState
= False
229 self
.fParameterIconTimer
= ICON_STATE_NULL
230 self
.fParameterList
= [] # index, widget
232 audioCountInfo
= host
.get_audio_port_count_info(self
.fPluginId
)
234 self
.fPeaksInputCount
= audioCountInfo
['ins']
235 self
.fPeaksOutputCount
= audioCountInfo
['outs']
237 if self
.fPeaksInputCount
> 2:
238 self
.fPeaksInputCount
= 2
240 if self
.fPeaksOutputCount
> 2:
241 self
.fPeaksOutputCount
= 2
243 self
.fAdjustViewableKnobCountScheduled
= False
245 # used during testing
246 self
.fIdleTimerId
= 0
248 # -------------------------------------------------------------
251 self
.fEditDialog
= PluginEdit(self
, host
, self
.fPluginId
)
253 # -------------------------------------------------------------
254 # Set-up common widgets (as none)
261 self
.cb_presets
= None
263 self
.label_name
= None
264 self
.label_presets
= None
265 self
.label_type
= None
267 self
.led_control
= None
269 self
.led_audio_in
= None
270 self
.led_audio_out
= None
275 self
.w_knobs_left
= None
276 self
.w_knobs_right
= None
277 self
.spacer_knobs
= None
279 # -------------------------------------------------------------
282 self
.customContextMenuRequested
.connect(self
.slot_showCustomMenu
)
283 host
.PluginRenamedCallback
.connect(self
.slot_handlePluginRenamedCallback
)
284 host
.PluginUnavailableCallback
.connect(self
.slot_handlePluginUnavailableCallback
)
285 host
.ParameterValueChangedCallback
.connect(self
.slot_handleParameterValueChangedCallback
)
286 host
.ParameterDefaultChangedCallback
.connect(self
.slot_handleParameterDefaultChangedCallback
)
287 host
.ParameterMappedControlIndexChangedCallback
.connect(self
.slot_handleParameterMappedControlIndexChangedCallback
)
288 host
.ParameterMappedRangeChangedCallback
.connect(self
.slot_handleParameterMappedRangeChangedCallback
)
289 host
.ParameterMidiChannelChangedCallback
.connect(self
.slot_handleParameterMidiChannelChangedCallback
)
290 host
.ProgramChangedCallback
.connect(self
.slot_handleProgramChangedCallback
)
291 host
.MidiProgramChangedCallback
.connect(self
.slot_handleMidiProgramChangedCallback
)
292 host
.OptionChangedCallback
.connect(self
.slot_handleOptionChangedCallback
)
293 host
.UiStateChangedCallback
.connect(self
.slot_handleUiStateChangedCallback
)
296 self
.sel_pen
= QPen(Qt
.cyan
, 1, Qt
.SolidLine
, Qt
.FlatCap
, Qt
.MiterJoin
)
297 self
.sel_pen
.setDashPattern([2.0, 4.0])
298 self
.sel_side_pen
= QPen(Qt
.cyan
, 2, Qt
.SolidLine
, Qt
.FlatCap
)
299 self
.shadow_pen
= QPen(Qt
.black
, 1)
301 # -----------------------------------------------------------------
304 def slot_handlePluginRenamedCallback(self
, pluginId
, newName
):
305 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
306 self
.setName(newName
)
309 def slot_handlePluginUnavailableCallback(self
, pluginId
, errorMsg
):
310 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
313 @pyqtSlot(int, int, float)
314 def slot_handleParameterValueChangedCallback(self
, pluginId
, index
, value
):
315 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
316 self
.setParameterValue(index
, value
, True)
318 @pyqtSlot(int, int, float)
319 def slot_handleParameterDefaultChangedCallback(self
, pluginId
, index
, value
):
320 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
321 self
.setParameterDefault(index
, value
)
323 @pyqtSlot(int, int, int)
324 def slot_handleParameterMappedControlIndexChangedCallback(self
, pluginId
, index
, ctrl
):
325 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
326 self
.setParameterMappedControlIndex(index
, ctrl
)
328 @pyqtSlot(int, int, float, float)
329 def slot_handleParameterMappedRangeChangedCallback(self
, pluginId
, index
, minimum
, maximum
):
330 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
331 self
.setParameterMappedRange(index
, minimum
, maximum
)
333 @pyqtSlot(int, int, int)
334 def slot_handleParameterMidiChannelChangedCallback(self
, pluginId
, index
, channel
):
335 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
336 self
.setParameterMidiChannel(index
, channel
)
339 def slot_handleProgramChangedCallback(self
, pluginId
, index
):
340 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
341 self
.setProgram(index
, True)
344 def slot_handleMidiProgramChangedCallback(self
, pluginId
, index
):
345 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
346 self
.setMidiProgram(index
, True)
348 @pyqtSlot(int, int, bool)
349 def slot_handleOptionChangedCallback(self
, pluginId
, option
, yesNo
):
350 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
351 self
.setOption(option
, yesNo
)
354 def slot_handleUiStateChangedCallback(self
, pluginId
, state
):
355 if self
.fEditDialog
is not None and self
.fPluginId
== pluginId
:
356 self
.customUiStateChanged(state
)
358 # ------------------------------------------------------------------
361 self
.fIsActive
= bool(self
.host
.get_internal_parameter_value(self
.fPluginId
, PARAMETER_ACTIVE
) >= 0.5)
363 isCalfSkin
= self
.fSkinStyle
.startswith("calf") and not isinstance(self
, PluginSlot_Compact
)
364 imageSuffix
= "white" if self
.fDarkStyle
else "black"
365 whiteLabels
= self
.fDarkStyle
367 if self
.fSkinStyle
.startswith("calf") or self
.fSkinStyle
.startswith("openav") or self
.fSkinStyle
in (
368 "3bandeq", "3bandsplitter", "pingpongpan", "nekobi", "calf_black", "zynfx"):
370 imageSuffix
= "white"
373 if self
.b_enable
is not None:
374 self
.b_enable
.setChecked(self
.fIsActive
)
375 self
.b_enable
.clicked
.connect(self
.slot_enableClicked
)
378 self
.b_enable
.setPixmaps(":/bitmaps/button_calf3.png",
379 ":/bitmaps/button_calf3_down.png",
380 ":/bitmaps/button_calf3.png")
382 self
.b_enable
.setSvgs(":/scalable/button_off.svg",
383 ":/scalable/button_on.svg",
384 ":/scalable/button_off.svg")
386 if self
.b_gui
is not None:
387 self
.b_gui
.clicked
.connect(self
.slot_showCustomUi
)
388 self
.b_gui
.setEnabled(bool(self
.fPluginInfo
['hints'] & PLUGIN_HAS_CUSTOM_UI
))
391 self
.b_gui
.setPixmaps(":/bitmaps/button_calf2.png",
392 ":/bitmaps/button_calf2_down.png",
393 ":/bitmaps/button_calf2_hover.png")
394 elif self
.fPluginInfo
['iconName'] == "distrho" or self
.fSkinStyle
in ("3bandeq", "3bandsplitter", "pingpongpan", "nekobi"):
395 self
.b_gui
.setPixmaps(":/bitmaps/button_distrho-{}.png".format(imageSuffix
),
396 ":/bitmaps/button_distrho_down-{}.png".format(imageSuffix
),
397 ":/bitmaps/button_distrho_hover-{}.png".format(imageSuffix
))
398 elif self
.fPluginInfo
['iconName'] == "file":
399 self
.b_gui
.setPixmaps(":/bitmaps/button_file-{}.png".format(imageSuffix
),
400 ":/bitmaps/button_file_down-{}.png".format(imageSuffix
),
401 ":/bitmaps/button_file_hover-{}.png".format(imageSuffix
))
403 if imageSuffix
== "black": # TODO
404 self
.b_gui
.setPixmaps(":/bitmaps/button_gui-{}.png".format(imageSuffix
),
405 ":/bitmaps/button_gui_down-{}.png".format(imageSuffix
),
406 ":/bitmaps/button_gui_hover-{}.png".format(imageSuffix
))
408 self
.b_gui
.setSvgs(":/scalable/button_gui-{}.svg".format(imageSuffix
),
409 ":/scalable/button_gui_down-{}.svg".format(imageSuffix
),
410 ":/scalable/button_gui_hover-{}.svg".format(imageSuffix
))
412 if self
.b_edit
is not None:
413 self
.b_edit
.clicked
.connect(self
.slot_showEditDialog
)
416 self
.b_edit
.setPixmaps(":/bitmaps/button_calf2.png",
417 ":/bitmaps/button_calf2_down.png",
418 ":/bitmaps/button_calf2_hover.png")
420 self
.b_edit
.setSvgs(":/scalable/button_edit-{}.svg".format(imageSuffix
),
421 ":/scalable/button_edit_down-{}.svg".format(imageSuffix
),
422 ":/scalable/button_edit_hover-{}.svg".format(imageSuffix
))
425 # Edit button *must* be available
426 self
.b_edit
= QPushButton(self
)
427 self
.b_edit
.setCheckable(True)
430 if self
.b_remove
is not None:
431 self
.b_remove
.clicked
.connect(self
.slot_removePlugin
)
433 if self
.label_name
is not None:
434 self
.label_name
.setEnabled(self
.fIsActive
)
435 self
.label_name
.setText(self
.fPluginInfo
['name'])
437 nameFont
= self
.label_name
.font()
439 if self
.fSkinStyle
.startswith("calf"):
440 nameFont
.setBold(True)
441 nameFont
.setPixelSize(12)
443 elif self
.fSkinStyle
.startswith("openav"):
444 QFontDatabase
.addApplicationFont(":/fonts/uranium.ttf")
445 nameFont
.setFamily("Uranium")
446 nameFont
.setPixelSize(15)
447 nameFont
.setCapitalization(QFont
.AllUppercase
)
450 nameFont
.setBold(True)
451 nameFont
.setPixelSize(11)
453 self
.label_name
.setFont(nameFont
)
455 if self
.label_presets
is not None:
456 presetFont
= self
.label_presets
.font()
457 presetFont
.setBold(True)
458 presetFont
.setPixelSize(10)
459 self
.label_presets
.setFont(presetFont
)
461 if self
.label_type
is not None:
462 self
.label_type
.setText(getPluginTypeAsString(self
.fPluginInfo
['type']))
464 if self
.led_control
is not None:
465 self
.led_control
.setColor(self
.led_control
.YELLOW
)
466 self
.led_control
.setEnabled(False)
468 if self
.led_midi
is not None:
469 self
.led_midi
.setColor(self
.led_midi
.RED
)
470 self
.led_midi
.setEnabled(False)
472 if self
.led_audio_in
is not None:
473 self
.led_audio_in
.setColor(self
.led_audio_in
.GREEN
)
474 self
.led_audio_in
.setEnabled(False)
476 if self
.led_audio_out
is not None:
477 self
.led_audio_out
.setColor(self
.led_audio_out
.BLUE
)
478 self
.led_audio_out
.setEnabled(False)
480 if self
.peak_in
is not None:
481 self
.peak_in
.setChannelCount(self
.fPeaksInputCount
)
482 self
.peak_in
.setMeterColor(DigitalPeakMeter
.COLOR_GREEN
)
483 self
.peak_in
.setMeterOrientation(DigitalPeakMeter
.HORIZONTAL
)
485 if self
.fSkinStyle
.startswith("calf"):
486 self
.peak_in
.setMeterStyle(DigitalPeakMeter
.STYLE_CALF
)
487 elif self
.fSkinStyle
== "rncbc":
488 self
.peak_in
.setMeterStyle(DigitalPeakMeter
.STYLE_RNCBC
)
489 elif self
.fSkinStyle
.startswith("openav") or self
.fSkinStyle
== "zynfx":
490 self
.peak_in
.setMeterStyle(DigitalPeakMeter
.STYLE_OPENAV
)
492 if self
.fPeaksInputCount
== 0 and not isinstance(self
, PluginSlot_Classic
):
495 if self
.peak_out
is not None:
496 self
.peak_out
.setChannelCount(self
.fPeaksOutputCount
)
497 self
.peak_out
.setMeterColor(DigitalPeakMeter
.COLOR_BLUE
)
498 self
.peak_out
.setMeterOrientation(DigitalPeakMeter
.HORIZONTAL
)
500 if self
.fSkinStyle
.startswith("calf"):
501 self
.peak_out
.setMeterStyle(DigitalPeakMeter
.STYLE_CALF
)
502 elif self
.fSkinStyle
== "rncbc":
503 self
.peak_out
.setMeterStyle(DigitalPeakMeter
.STYLE_RNCBC
)
504 elif self
.fSkinStyle
.startswith("openav") or self
.fSkinStyle
== "zynfx":
505 self
.peak_out
.setMeterStyle(DigitalPeakMeter
.STYLE_OPENAV
)
507 if self
.fPeaksOutputCount
== 0 and not isinstance(self
, PluginSlot_Classic
):
510 # -------------------------------------------------------------
512 if self
.fSkinStyle
== "openav":
514 QFrame#PluginWidget {
515 background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
516 stop: 0 #383838, stop: %f #111111, stop: 1.0 #111111);
518 QLabel#label_name { color: #FFFFFF; }
519 QLabel#label_name:disabled { color: #505050; }
520 """ % (0.95 if isinstance(self
, PluginSlot_Compact
) else 0.35)
522 elif self
.fSkinStyle
== "openav-old":
524 QFrame#PluginWidget {
525 background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
526 stop: 0 #303030, stop: %f #111111, stop: 1.0 #111111);
528 QLabel#label_name { color: #FF5100; }
529 QLabel#label_name:disabled { color: #505050; }
530 """ % (0.95 if isinstance(self
, PluginSlot_Compact
) else 0.35)
533 colorEnabled
= "#BBB"
534 colorDisabled
= "#555"
536 if self
.fSkinStyle
in ("3bandeq", "calf_black", "calf_blue", "nekobi", "zynfx"):
537 styleSheet2
= "background-image: url(:/bitmaps/background_%s.png);" % self
.fSkinStyle
539 styleSheet2
= "background-color: rgb(200, 200, 200);"
540 styleSheet2
+= "background-image: url(:/bitmaps/background_noise1.png);"
542 if not self
.fDarkStyle
:
543 colorEnabled
= "#111"
544 colorDisabled
= "#AAA"
547 QFrame#PluginWidget {
549 background-repeat: repeat-xy;
552 QLabel#label_audio_in,
553 QLabel#label_audio_out,
555 QLabel#label_presets { color: %s; }
556 QLabel#label_name:disabled { color: %s; }
557 """ % (styleSheet2
, colorEnabled
, colorDisabled
)
560 QComboBox#cb_presets,
561 QLabel#label_audio_in,
562 QLabel#label_audio_out,
563 QLabel#label_midi { font-size: 10px; }
565 self
.setStyleSheet(styleSheet
)
567 # -------------------------------------------------------------
570 if self
.w_knobs_left
is not None:
571 parameterCount
= self
.host
.get_parameter_count(self
.fPluginId
)
574 layout
= self
.w_knobs_left
.layout()
575 for i
in range(parameterCount
):
576 # 50 should be enough for everybody, right?
580 paramInfo
= self
.host
.get_parameter_info(self
.fPluginId
, i
)
581 paramData
= self
.host
.get_parameter_data(self
.fPluginId
, i
)
582 paramRanges
= self
.host
.get_parameter_ranges(self
.fPluginId
, i
)
583 isInteger
= (paramData
['hints'] & PARAMETER_IS_INTEGER
) != 0
585 if paramData
['type'] != PARAMETER_INPUT
:
587 if paramData
['hints'] & PARAMETER_IS_BOOLEAN
:
589 if (paramData
['hints'] & PARAMETER_IS_ENABLED
) == 0:
591 if (paramData
['hints'] & PARAMETER_USES_SCALEPOINTS
) != 0 and not isInteger
:
592 # NOTE: we assume integer scalepoints are continuous
594 if isInteger
and paramRanges
['max']-paramRanges
['min'] <= 3:
596 if paramInfo
['name'].startswith("unused"):
599 paramName
= getParameterShortName(paramInfo
['name'])
601 widget
= ScalableDial(self
, i
)
602 widget
.setLabel(paramName
)
603 widget
.setMinimum(paramRanges
['min'])
604 widget
.setMaximum(paramRanges
['max'])
608 widget
.setPrecision(paramRanges
['max']-paramRanges
['min'], True)
610 setScalableDialStyle(widget
, i
, parameterCount
, whiteLabels
, self
.fSkinStyle
)
613 self
.fParameterList
.append([i
, widget
])
614 layout
.addWidget(widget
)
616 if self
.w_knobs_right
is not None and (self
.fPluginInfo
['hints'] & PLUGIN_CAN_DRYWET
) != 0:
617 widget
= ScalableDial(self
, PARAMETER_DRYWET
)
618 widget
.setLabel("Dry/Wet")
619 widget
.setMinimum(0.0)
620 widget
.setMaximum(1.0)
621 setScalableDialStyle(widget
, PARAMETER_DRYWET
, 0, whiteLabels
, self
.fSkinStyle
)
623 self
.fParameterList
.append([PARAMETER_DRYWET
, widget
])
624 self
.w_knobs_right
.layout().addWidget(widget
)
626 if self
.w_knobs_right
is not None and (self
.fPluginInfo
['hints'] & PLUGIN_CAN_VOLUME
) != 0:
627 widget
= ScalableDial(self
, PARAMETER_VOLUME
)
628 widget
.setLabel("Volume")
629 widget
.setMinimum(0.0)
630 widget
.setMaximum(1.27)
631 setScalableDialStyle(widget
, PARAMETER_VOLUME
, 0, whiteLabels
, self
.fSkinStyle
)
633 self
.fParameterList
.append([PARAMETER_VOLUME
, widget
])
634 self
.w_knobs_right
.layout().addWidget(widget
)
636 for paramIndex
, paramWidget
in self
.fParameterList
:
637 paramWidget
.setContextMenuPolicy(Qt
.CustomContextMenu
)
638 paramWidget
.customContextMenuRequested
.connect(self
.slot_knobCustomMenu
)
639 paramWidget
.dragStateChanged
.connect(self
.slot_parameterDragStateChanged
)
640 paramWidget
.realValueChanged
.connect(self
.slot_parameterValueChanged
)
641 paramWidget
.blockSignals(True)
642 paramWidget
.setValue(self
.host
.get_internal_parameter_value(self
.fPluginId
, paramIndex
))
643 paramWidget
.blockSignals(False)
645 # -------------------------------------------------------------
647 self
.setWindowTitle(self
.fPluginInfo
['name'])
649 if not self
.fAdjustViewableKnobCountScheduled
:
650 self
.fAdjustViewableKnobCountScheduled
= True
651 QTimer
.singleShot(5, self
.adjustViewableKnobCount
)
653 # -----------------------------------------------------------------
655 def getFixedHeight(self
):
659 return self
.fPluginInfo
['hints']
661 def getPluginId(self
):
662 return self
.fPluginId
664 # -----------------------------------------------------------------
666 def setPluginId(self
, idx
):
668 self
.fEditDialog
.setPluginId(idx
)
670 def setName(self
, name
):
671 self
.fPluginInfo
['name'] = name
672 self
.fEditDialog
.setName(name
)
674 if self
.label_name
is not None:
675 self
.label_name
.setText(name
)
677 def setSelected(self
, yesNo
):
678 if self
.fIsSelected
== yesNo
:
681 self
.fIsSelected
= yesNo
684 # -----------------------------------------------------------------
686 def setActive(self
, active
, sendCallback
=False, sendHost
=True):
687 self
.fIsActive
= active
690 self
.fParameterIconTimer
= ICON_STATE_ON
691 self
.activeChanged(active
)
694 self
.host
.set_active(self
.fPluginId
, active
)
697 self
.fEditDialog
.clearNotes()
698 self
.midiActivityChanged(False)
700 if self
.label_name
is not None:
701 self
.label_name
.setEnabled(self
.fIsActive
)
703 # called from rack, checks if param is possible first
704 def setInternalParameter(self
, parameterId
, value
):
705 if parameterId
<= PARAMETER_MAX
or parameterId
>= PARAMETER_NULL
:
708 elif parameterId
== PARAMETER_ACTIVE
:
709 return self
.setActive(bool(value
), True, True)
711 elif parameterId
== PARAMETER_DRYWET
:
712 if (self
.fPluginInfo
['hints'] & PLUGIN_CAN_DRYWET
) == 0: return
713 self
.host
.set_drywet(self
.fPluginId
, value
)
715 elif parameterId
== PARAMETER_VOLUME
:
716 if (self
.fPluginInfo
['hints'] & PLUGIN_CAN_VOLUME
) == 0: return
717 self
.host
.set_volume(self
.fPluginId
, value
)
719 elif parameterId
== PARAMETER_BALANCE_LEFT
:
720 if (self
.fPluginInfo
['hints'] & PLUGIN_CAN_BALANCE
) == 0: return
721 self
.host
.set_balance_left(self
.fPluginId
, value
)
723 elif parameterId
== PARAMETER_BALANCE_RIGHT
:
724 if (self
.fPluginInfo
['hints'] & PLUGIN_CAN_BALANCE
) == 0: return
725 self
.host
.set_balance_right(self
.fPluginId
, value
)
727 elif parameterId
== PARAMETER_PANNING
:
728 if (self
.fPluginInfo
['hints'] & PLUGIN_CAN_PANNING
) == 0: return
729 self
.host
.set_panning(self
.fPluginId
, value
)
731 elif parameterId
== PARAMETER_CTRL_CHANNEL
:
732 self
.host
.set_ctrl_channel(self
.fPluginId
, value
)
734 self
.fEditDialog
.setParameterValue(parameterId
, value
)
736 # -----------------------------------------------------------------
738 def setParameterValue(self
, parameterId
, value
, sendCallback
):
739 if parameterId
== PARAMETER_ACTIVE
:
740 return self
.setActive(bool(value
), True, False)
742 self
.fEditDialog
.setParameterValue(parameterId
, value
)
745 self
.fParameterIconTimer
= ICON_STATE_ON
746 self
.editDialogParameterValueChanged(self
.fPluginId
, parameterId
, value
)
748 def setParameterDefault(self
, parameterId
, value
):
749 self
.fEditDialog
.setParameterDefault(parameterId
, value
)
751 def setParameterMappedControlIndex(self
, parameterId
, control
):
752 self
.fEditDialog
.setParameterMappedControlIndex(parameterId
, control
)
754 def setParameterMappedRange(self
, parameterId
, minimum
, maximum
):
755 self
.fEditDialog
.setParameterMappedRange(parameterId
, minimum
, maximum
)
757 def setParameterMidiChannel(self
, parameterId
, channel
):
758 self
.fEditDialog
.setParameterMidiChannel(parameterId
, channel
)
760 # -----------------------------------------------------------------
762 def setProgram(self
, index
, sendCallback
):
763 self
.fEditDialog
.setProgram(index
)
766 self
.fParameterIconTimer
= ICON_STATE_ON
767 self
.editDialogProgramChanged(self
.fPluginId
, index
)
769 self
.updateParameterValues()
771 def setMidiProgram(self
, index
, sendCallback
):
772 self
.fEditDialog
.setMidiProgram(index
)
775 self
.fParameterIconTimer
= ICON_STATE_ON
776 self
.editDialogMidiProgramChanged(self
.fPluginId
, index
)
778 self
.updateParameterValues()
780 # -----------------------------------------------------------------
782 def setOption(self
, option
, yesNo
):
783 self
.fEditDialog
.setOption(option
, yesNo
)
785 # -----------------------------------------------------------------
787 def showCustomUI(self
):
788 self
.host
.show_custom_ui(self
.fPluginId
, True)
790 if self
.b_gui
is not None:
791 self
.b_gui
.setChecked(True)
793 def hideCustomUI(self
):
794 self
.host
.show_custom_ui(self
.fPluginId
, False)
796 if self
.b_gui
is not None:
797 self
.b_gui
.setChecked(False)
799 def showEditDialog(self
):
800 self
.fEditDialog
.show()
801 self
.fEditDialog
.activateWindow()
803 if self
.b_edit
is not None:
804 self
.b_edit
.setChecked(True)
806 def showRenameDialog(self
):
807 oldName
= self
.fPluginInfo
['name']
808 newNameTry
= QInputDialog
.getText(self
, self
.tr("Rename Plugin"), self
.tr("New plugin name:"), QLineEdit
.Normal
, oldName
)
810 if not (newNameTry
[1] and newNameTry
[0] and oldName
!= newNameTry
[0]):
813 newName
= newNameTry
[0]
815 if not self
.host
.rename_plugin(self
.fPluginId
, newName
):
816 CustomMessageBox(self
, QMessageBox
.Warning, self
.tr("Error"), self
.tr("Operation failed"),
817 self
.host
.get_last_error(), QMessageBox
.Ok
, QMessageBox
.Ok
)
820 def showReplaceDialog(self
):
821 data
= gCarla
.gui
.showAddPluginDialog()
826 btype
, ptype
, filename
, label
, uniqueId
, extraPtr
= data
828 if not self
.host
.replace_plugin(self
.fPluginId
):
829 CustomMessageBox(self
, QMessageBox
.Critical
, self
.tr("Error"), self
.tr("Failed to replace plugin"), self
.host
.get_last_error(), QMessageBox
.Ok
, QMessageBox
.Ok
)
832 ok
= self
.host
.add_plugin(btype
, ptype
, filename
, None, label
, uniqueId
, extraPtr
, PLUGIN_OPTIONS_NULL
)
834 self
.host
.replace_plugin(self
.host
.get_max_plugin_number())
837 CustomMessageBox(self
, QMessageBox
.Critical
, self
.tr("Error"), self
.tr("Failed to load plugin"), self
.host
.get_last_error(), QMessageBox
.Ok
, QMessageBox
.Ok
)
839 # -----------------------------------------------------------------
841 def activeChanged(self
, onOff
):
842 self
.fIsActive
= onOff
844 if self
.b_enable
is None:
847 self
.b_enable
.blockSignals(True)
848 self
.b_enable
.setChecked(onOff
)
849 self
.b_enable
.blockSignals(False)
851 def customUiStateChanged(self
, state
):
852 if self
.b_gui
is None:
855 self
.b_gui
.blockSignals(True)
857 self
.b_gui
.setChecked(False)
858 self
.b_gui
.setEnabled(True)
860 self
.b_gui
.setChecked(True)
861 self
.b_gui
.setEnabled(True)
863 self
.b_gui
.setChecked(False)
864 self
.b_gui
.setEnabled(False)
865 self
.b_gui
.blockSignals(False)
867 def parameterActivityChanged(self
, onOff
):
868 if self
.led_control
is None:
871 self
.led_control
.setChecked(onOff
)
873 def midiActivityChanged(self
, onOff
):
874 if self
.led_midi
is None:
877 self
.led_midi
.setChecked(onOff
)
879 def optionChanged(self
, option
, yesNo
):
882 # -----------------------------------------------------------------
883 # PluginEdit callbacks
885 def editDialogVisibilityChanged(self
, pluginId
, visible
):
886 if self
.b_edit
is None:
889 self
.b_edit
.blockSignals(True)
890 self
.b_edit
.setChecked(visible
)
891 self
.b_edit
.blockSignals(False)
893 def editDialogPluginHintsChanged(self
, pluginId
, hints
):
894 self
.fPluginInfo
['hints'] = hints
896 for paramIndex
, paramWidget
in self
.fParameterList
:
897 if paramIndex
== PARAMETER_DRYWET
:
898 paramWidget
.setVisible(hints
& PLUGIN_CAN_DRYWET
)
899 elif paramIndex
== PARAMETER_VOLUME
:
900 paramWidget
.setVisible(hints
& PLUGIN_CAN_VOLUME
)
902 if self
.b_gui
is not None:
903 self
.b_gui
.setEnabled(bool(hints
& PLUGIN_HAS_CUSTOM_UI
))
905 def editDialogParameterValueChanged(self
, pluginId
, parameterId
, value
):
906 for paramIndex
, paramWidget
in self
.fParameterList
:
907 if paramIndex
!= parameterId
:
910 paramWidget
.blockSignals(True)
911 paramWidget
.setValue(value
)
912 paramWidget
.blockSignals(False)
915 def editDialogProgramChanged(self
, pluginId
, index
):
916 if self
.cb_presets
is None:
919 self
.cb_presets
.blockSignals(True)
920 self
.cb_presets
.setCurrentIndex(index
)
921 self
.cb_presets
.blockSignals(False)
924 self
.updateParameterValues()
926 def editDialogMidiProgramChanged(self
, pluginId
, index
):
927 if self
.cb_presets
is None:
930 self
.cb_presets
.blockSignals(True)
931 self
.cb_presets
.setCurrentIndex(index
)
932 self
.cb_presets
.blockSignals(False)
935 self
.updateParameterValues()
937 def editDialogNotePressed(self
, pluginId
, note
):
940 def editDialogNoteReleased(self
, pluginId
, note
):
943 def editDialogMidiActivityChanged(self
, pluginId
, onOff
):
944 self
.midiActivityChanged(onOff
)
946 # -----------------------------------------------------------------
950 if self
.fPeaksInputCount
> 0:
951 if self
.fPeaksInputCount
> 1:
952 peak1
= self
.host
.get_input_peak_value(self
.fPluginId
, True)
953 peak2
= self
.host
.get_input_peak_value(self
.fPluginId
, False)
954 ledState
= bool(peak1
!= 0.0 or peak2
!= 0.0)
956 if self
.peak_in
is not None:
957 self
.peak_in
.displayMeter(1, peak1
)
958 self
.peak_in
.displayMeter(2, peak2
)
961 peak
= self
.host
.get_input_peak_value(self
.fPluginId
, True)
962 ledState
= bool(peak
!= 0.0)
964 if self
.peak_in
is not None:
965 self
.peak_in
.displayMeter(1, peak
)
967 if self
.fLastGreenLedState
!= ledState
and self
.led_audio_in
is not None:
968 self
.fLastGreenLedState
= ledState
969 self
.led_audio_in
.setChecked(ledState
)
972 if self
.fPeaksOutputCount
> 0:
973 if self
.fPeaksOutputCount
> 1:
974 peak1
= self
.host
.get_output_peak_value(self
.fPluginId
, True)
975 peak2
= self
.host
.get_output_peak_value(self
.fPluginId
, False)
976 ledState
= bool(peak1
!= 0.0 or peak2
!= 0.0)
978 if self
.peak_out
is not None:
979 self
.peak_out
.displayMeter(1, peak1
)
980 self
.peak_out
.displayMeter(2, peak2
)
983 peak
= self
.host
.get_output_peak_value(self
.fPluginId
, True)
984 ledState
= bool(peak
!= 0.0)
986 if self
.peak_out
is not None:
987 self
.peak_out
.displayMeter(1, peak
)
989 if self
.fLastBlueLedState
!= ledState
and self
.led_audio_out
is not None:
990 self
.fLastBlueLedState
= ledState
991 self
.led_audio_out
.setChecked(ledState
)
994 if self
.fParameterIconTimer
== ICON_STATE_ON
:
995 self
.parameterActivityChanged(True)
996 self
.fParameterIconTimer
= ICON_STATE_WAIT
998 elif self
.fParameterIconTimer
== ICON_STATE_WAIT
:
999 self
.fParameterIconTimer
= ICON_STATE_OFF
1001 elif self
.fParameterIconTimer
== ICON_STATE_OFF
:
1002 self
.parameterActivityChanged(False)
1003 self
.fParameterIconTimer
= ICON_STATE_NULL
1005 self
.fEditDialog
.idleSlow()
1007 # -----------------------------------------------------------------
1009 def drawOutline(self
, painter
):
1011 painter
.setBrush(Qt
.transparent
)
1012 w
= float(self
.width())
1013 h
= float(self
.height())
1015 painter
.setPen(self
.shadow_pen
)
1016 painter
.drawLine(QLineF(0.5, h
-1, w
-1, h
-1))
1018 if self
.fIsSelected
:
1019 painter
.setCompositionMode(QPainter
.CompositionMode_Plus
)
1021 painter
.setPen(self
.sel_pen
)
1022 painter
.drawRect(QRectF(0.5, 0.5, w
-1, h
-1))
1023 sidelines
= [QLineF(1, 1, 1, h
-1), QLineF(w
-1, 1, w
-1, h
-1)]
1024 painter
.setPen(self
.sel_side_pen
)
1025 painter
.drawLines(sidelines
)
1027 painter
.setCompositionMode(QPainter
.CompositionMode_SourceOver
)
1031 def updateParameterValues(self
):
1032 for paramIndex
, paramWidget
in self
.fParameterList
:
1036 paramWidget
.blockSignals(True)
1037 paramWidget
.setValue(self
.host
.get_current_parameter_value(self
.fPluginId
, paramIndex
))
1038 paramWidget
.blockSignals(False)
1040 # -----------------------------------------------------------------
1043 def slot_enableClicked(self
, yesNo
):
1044 self
.setActive(yesNo
, False, True)
1047 def slot_showCustomMenu(self
):
1050 # -------------------------------------------------------------
1051 # Expand/Minimize and Tweaks
1053 actCompact
= menu
.addAction(self
.tr("Expand") if isinstance(self
, PluginSlot_Compact
) else self
.tr("Minimize"))
1054 actColor
= menu
.addAction(self
.tr("Change Color..."))
1055 actSkin
= menu
.addAction(self
.tr("Change Skin..."))
1058 # -------------------------------------------------------------
1059 # Find in patchbay, if possible
1061 if self
.host
.processMode
in (ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
,
1062 ENGINE_PROCESS_MODE_PATCHBAY
):
1063 actFindInPatchbay
= menu
.addAction(self
.tr("Find plugin in patchbay"))
1067 actFindInPatchbay
= None
1069 # -------------------------------------------------------------
1072 actMoveUp
= menu
.addAction(self
.tr("Move Up"))
1073 actMoveDown
= menu
.addAction(self
.tr("Move Down"))
1075 if self
.fPluginId
== 0:
1076 actMoveUp
.setEnabled(False)
1077 if self
.fPluginId
>= self
.fParent
.getPluginCount():
1078 actMoveDown
.setEnabled(False)
1080 # -------------------------------------------------------------
1081 # Bypass and Enable/Disable
1083 actBypass
= menu
.addAction(self
.tr("Bypass"))
1084 actEnable
= menu
.addAction(self
.tr("Disable") if self
.fIsActive
else self
.tr("Enable"))
1087 if self
.fPluginInfo
['hints'] & PLUGIN_CAN_DRYWET
:
1088 actBypass
.setCheckable(True)
1089 actBypass
.setChecked(self
.host
.get_internal_parameter_value(self
.fPluginId
, PARAMETER_DRYWET
) == 0.0)
1091 actBypass
.setVisible(False)
1093 # -------------------------------------------------------------
1094 # Reset and Randomize parameters
1096 actReset
= menu
.addAction(self
.tr("Reset parameters"))
1097 actRandom
= menu
.addAction(self
.tr("Randomize parameters"))
1100 # -------------------------------------------------------------
1101 # Edit and Show Custom UI
1103 actEdit
= menu
.addAction(self
.tr("Edit"))
1104 actGui
= menu
.addAction(self
.tr("Show Custom UI"))
1107 if self
.b_edit
is not None:
1108 actEdit
.setCheckable(True)
1109 actEdit
.setChecked(self
.b_edit
.isChecked())
1111 actEdit
.setVisible(False)
1113 if self
.b_gui
is not None:
1114 actGui
.setCheckable(True)
1115 actGui
.setChecked(self
.b_gui
.isChecked())
1116 actGui
.setEnabled(self
.b_gui
.isEnabled())
1118 actGui
.setVisible(False)
1120 # -------------------------------------------------------------
1123 actClone
= menu
.addAction(self
.tr("Clone"))
1124 actRename
= menu
.addAction(self
.tr("Rename..."))
1125 actReplace
= menu
.addAction(self
.tr("Replace..."))
1126 actRemove
= menu
.addAction(self
.tr("Remove"))
1128 if self
.fIdleTimerId
!= 0:
1129 actRemove
.setVisible(False)
1131 if self
.host
.exportLV2
:
1133 actExportLV2
= menu
.addAction(self
.tr("Export LV2..."))
1138 # -------------------------------------------------------------
1141 actSel
= menu
.exec_(QCursor
.pos())
1146 # -------------------------------------------------------------
1149 elif actSel
== actCompact
:
1151 gCarla
.gui
.compactPlugin(self
.fPluginId
)
1153 # -------------------------------------------------------------
1156 elif actSel
== actColor
:
1157 initial
= QColor(self
.fSkinColor
[0], self
.fSkinColor
[1], self
.fSkinColor
[2])
1158 color
= QColorDialog
.getColor(initial
, self
, self
.tr("Change Color"), QColorDialog
.DontUseNativeDialog
)
1160 if not color
.isValid():
1163 color
= color
.getRgb()[0:3]
1164 colorStr
= "%i;%i;%i" % color
1165 gCarla
.gui
.changePluginColor(self
.fPluginId
, color
, colorStr
)
1167 elif actSel
== actSkin
:
1182 index
= skinList
.index(self
.fSkinStyle
)
1186 skin
= QInputDialog
.getItem(self
, self
.tr("Change Skin"),
1187 self
.tr("Change Skin to:"),
1188 skinList
, index
, False)
1191 gCarla
.gui
.changePluginSkin(self
.fPluginId
, skin
[0])
1193 # -------------------------------------------------------------
1196 elif actSel
== actFindInPatchbay
:
1197 gCarla
.gui
.findPluginInPatchbay(self
.fPluginId
)
1199 # -------------------------------------------------------------
1202 elif actSel
== actMoveUp
:
1203 gCarla
.gui
.switchPlugins(self
.fPluginId
, self
.fPluginId
-1)
1205 elif actSel
== actMoveDown
:
1206 gCarla
.gui
.switchPlugins(self
.fPluginId
, self
.fPluginId
+1)
1208 # -------------------------------------------------------------
1209 # Bypass and Enable/Disable
1211 elif actSel
== actBypass
:
1212 value
= 0.0 if actBypass
.isChecked() else 1.0
1213 self
.host
.set_drywet(self
.fPluginId
, value
)
1214 self
.setParameterValue(PARAMETER_DRYWET
, value
, True)
1216 elif actSel
== actEnable
:
1217 self
.setActive(not self
.fIsActive
, True, True)
1219 # -------------------------------------------------------------
1220 # Reset and Randomize parameters
1222 elif actSel
== actReset
:
1223 self
.host
.reset_parameters(self
.fPluginId
)
1225 elif actSel
== actRandom
:
1226 self
.host
.randomize_parameters(self
.fPluginId
)
1228 # -------------------------------------------------------------
1229 # Edit and Show Custom UI
1231 elif actSel
== actEdit
:
1234 elif actSel
== actGui
:
1237 # -------------------------------------------------------------
1240 elif actSel
== actClone
:
1241 if not self
.host
.clone_plugin(self
.fPluginId
):
1242 CustomMessageBox(self
, QMessageBox
.Warning, self
.tr("Error"), self
.tr("Operation failed"),
1243 self
.host
.get_last_error(), QMessageBox
.Ok
, QMessageBox
.Ok
)
1245 # -------------------------------------------------------------
1248 elif actSel
== actRename
:
1249 self
.showRenameDialog()
1251 # -------------------------------------------------------------
1254 elif actSel
== actReplace
:
1255 self
.showReplaceDialog()
1257 # -------------------------------------------------------------
1260 elif actSel
== actRemove
:
1261 if not self
.host
.remove_plugin(self
.fPluginId
):
1262 CustomMessageBox(self
, QMessageBox
.Warning, self
.tr("Error"), self
.tr("Operation failed"),
1263 self
.host
.get_last_error(), QMessageBox
.Ok
, QMessageBox
.Ok
)
1265 # -------------------------------------------------------------
1268 elif actSel
== actExportLV2
:
1269 filepath
= QInputDialog
.getItem(self
, self
.tr("Export LV2 Plugin"),
1270 self
.tr("Select LV2 Path where plugin will be exported to:"),
1271 CARLA_DEFAULT_LV2_PATH
, editable
=False)
1272 if not all(filepath
):
1275 plugname
= self
.fPluginInfo
['name']
1276 filepath
= os
.path
.join(filepath
[0], plugname
.replace(" ","_"))
1278 if not filepath
.endswith(".lv2"):
1281 if os
.path
.exists(filepath
):
1282 if QMessageBox
.question(self
, self
.tr("Export to LV2"),
1283 self
.tr("Plugin bundle already exists, overwrite?")) == QMessageBox
.Ok
:
1286 if not self
.host
.export_plugin_lv2(self
.fPluginId
, filepath
):
1287 return CustomMessageBox(self
, QMessageBox
.Warning, self
.tr("Error"), self
.tr("Operation failed"),
1288 self
.host
.get_last_error(), QMessageBox
.Ok
, QMessageBox
.Ok
)
1290 QMessageBox
.information(self
, self
.tr("Plugin exported"),
1291 self
.tr("Plugin exported successfully, saved in folder:\n%s" % filepath
))
1293 # -------------------------------------------------------------
1296 def slot_knobCustomMenu(self
):
1297 sender
= self
.sender()
1298 index
= sender
.fIndex
1299 minimum
= sender
.fMinimum
1300 maximum
= sender
.fMaximum
1301 current
= sender
.fRealValue
1302 label
= sender
.fLabel
1304 if index
in (PARAMETER_NULL
, PARAMETER_CTRL_CHANNEL
) or index
<= PARAMETER_MAX
:
1306 elif index
in (PARAMETER_DRYWET
, PARAMETER_VOLUME
):
1308 elif index
== PARAMETER_BALANCE_LEFT
:
1310 elif index
== PARAMETER_BALANCE_RIGHT
:
1312 elif index
== PARAMETER_PANNING
:
1315 default
= self
.host
.get_default_parameter_value(self
.fPluginId
, index
)
1317 if index
< PARAMETER_NULL
:
1318 # show in integer percentage
1319 textReset
= self
.tr("Reset (%i%%)" % round(default
*100.0))
1320 textMinim
= self
.tr("Set to Minimum (%i%%)" % round(minimum
*100.0))
1321 textMaxim
= self
.tr("Set to Maximum (%i%%)" % round(maximum
*100.0))
1323 # show in full float value
1324 textReset
= self
.tr("Reset (%f)" % default
)
1325 textMinim
= self
.tr("Set to Minimum (%f)" % minimum
)
1326 textMaxim
= self
.tr("Set to Maximum (%f)" % maximum
)
1329 actReset
= menu
.addAction(textReset
)
1331 actMinimum
= menu
.addAction(textMinim
)
1332 actCenter
= menu
.addAction(self
.tr("Set to Center"))
1333 actMaximum
= menu
.addAction(textMaxim
)
1335 actSet
= menu
.addAction(self
.tr("Set value..."))
1337 if index
> PARAMETER_NULL
or index
not in (PARAMETER_BALANCE_LEFT
, PARAMETER_BALANCE_RIGHT
, PARAMETER_PANNING
):
1338 menu
.removeAction(actCenter
)
1340 actSelected
= menu
.exec_(QCursor
.pos())
1342 if actSelected
== actSet
:
1343 if index
< PARAMETER_NULL
:
1344 value
, ok
= QInputDialog
.getInt(self
, self
.tr("Set value"), label
, round(current
*100), round(minimum
*100), round(maximum
*100), 1)
1349 value
= float(value
)/100.0
1352 paramInfo
= self
.host
.get_parameter_info(self
.fPluginId
, index
)
1353 paramRanges
= self
.host
.get_parameter_ranges(self
.fPluginId
, index
)
1356 for i
in range(paramInfo
['scalePointCount']):
1357 scalePoints
.append(self
.host
.get_parameter_scalepoint_info(self
.fPluginId
, index
, i
))
1360 suffix
= paramInfo
['unit'].strip()
1362 if suffix
== "(coef)":
1366 suffix
= " " + suffix
1368 dialog
= CustomInputDialog(self
, label
, current
, minimum
, maximum
,
1369 paramRanges
['step'], paramRanges
['stepSmall'], scalePoints
, prefix
, suffix
)
1371 if not dialog
.exec_():
1374 value
= dialog
.returnValue()
1376 elif actSelected
== actMinimum
:
1378 elif actSelected
== actMaximum
:
1380 elif actSelected
== actReset
:
1382 elif actSelected
== actCenter
:
1387 sender
.setValue(value
, True)
1389 # -----------------------------------------------------------------
1392 def slot_showCustomUi(self
, show
):
1393 self
.host
.show_custom_ui(self
.fPluginId
, show
)
1396 def slot_showEditDialog(self
, show
):
1397 self
.fEditDialog
.setVisible(show
)
1400 def slot_removePlugin(self
):
1401 if not self
.host
.remove_plugin(self
.fPluginId
):
1402 CustomMessageBox(self
, QMessageBox
.Warning, self
.tr("Error"), self
.tr("Operation failed"),
1403 self
.host
.get_last_error(), QMessageBox
.Ok
, QMessageBox
.Ok
)
1405 # -----------------------------------------------------------------
1408 def slot_parameterDragStateChanged(self
, touch
):
1409 index
= self
.sender().getIndex()
1412 self
.host
.set_parameter_touch(self
.fPluginId
, index
, touch
)
1415 def slot_parameterValueChanged(self
, value
):
1416 index
= self
.sender().getIndex()
1419 self
.setInternalParameter(index
, value
)
1421 self
.host
.set_parameter_value(self
.fPluginId
, index
, value
)
1422 self
.setParameterValue(index
, value
, False)
1425 def slot_programChanged(self
, index
):
1426 self
.host
.set_program(self
.fPluginId
, index
)
1427 self
.setProgram(index
, False)
1430 def slot_midiProgramChanged(self
, index
):
1431 self
.host
.set_midi_program(self
.fPluginId
, index
)
1432 self
.setMidiProgram(index
, False)
1434 # -----------------------------------------------------------------
1436 def adjustViewableKnobCount(self
):
1437 if self
.w_knobs_left
is None or self
.spacer_knobs
is None:
1441 maxWidth
= self
.w_knobs_left
.width() + self
.spacer_knobs
.geometry().width() + 2
1443 plen
= len(self
.fParameterList
)
1444 for i
in range(plen
):
1445 index
, widget
= self
.fParameterList
[i
]
1449 curWidth
+= widget
.width() + 4
1451 if curWidth
+ widget
.width() * 2 + 8 < maxWidth
:
1452 #if not widget.isVisible():
1456 for i2
in range(i
, plen
):
1457 index2
, widget2
= self
.fParameterList
[i2
]
1460 #if widget2.isVisible():
1465 self
.fAdjustViewableKnobCountScheduled
= False
1467 def testTimer(self
):
1468 self
.fIdleTimerId
= self
.startTimer(25)
1470 # -----------------------------------------------------------------
1472 def mouseDoubleClickEvent(self
, event
):
1473 QFrame
.mouseDoubleClickEvent(self
, event
)
1476 gCarla
.gui
.compactPlugin(self
.fPluginId
)
1478 def closeEvent(self
, event
):
1479 if self
.fIdleTimerId
!= 0:
1480 self
.killTimer(self
.fIdleTimerId
)
1481 self
.fIdleTimerId
= 0
1483 self
.host
.engine_close()
1485 QFrame
.closeEvent(self
, event
)
1487 def resizeEvent(self
, event
):
1488 if not self
.fAdjustViewableKnobCountScheduled
:
1489 self
.fAdjustViewableKnobCountScheduled
= True
1490 QTimer
.singleShot(100, self
.adjustViewableKnobCount
)
1491 QFrame
.resizeEvent(self
, event
)
1493 def timerEvent(self
, event
):
1494 if event
.timerId() == self
.fIdleTimerId
:
1495 self
.host
.engine_idle()
1499 QFrame
.timerEvent(self
, event
)
1501 def paintEvent(self
, event
):
1502 painter
= QPainter(self
)
1505 if self
.fSkinColor
!= (0,0,0):
1506 painter
.setCompositionMode(QPainter
.CompositionMode_Multiply
)
1507 r
,g
,b
= self
.fSkinColor
1508 painter
.setBrush(QColor(r
,g
,b
))
1509 painter
.setPen(Qt
.NoPen
)
1510 painter
.drawRect(QRectF(0,0,self
.width(),self
.height()))
1511 painter
.setCompositionMode(QPainter
.CompositionMode_SourceOver
)
1513 self
.drawOutline(painter
)
1514 QFrame
.paintEvent(self
, event
)
1516 # ------------------------------------------------------------------------------------------------------------
1518 class PluginSlot_Calf(AbstractPluginSlot
):
1519 def __init__(self
, parent
, host
, pluginId
, skinColor
, skinStyle
):
1520 AbstractPluginSlot
.__init
__(self
, parent
, host
, pluginId
, skinColor
, skinStyle
)
1521 self
.ui
= ui_carla_plugin_calf
.Ui_PluginWidget()
1522 self
.ui
.setupUi(self
)
1524 audioCount
= self
.host
.get_audio_port_count_info(self
.fPluginId
)
1525 midiCount
= self
.host
.get_midi_port_count_info(self
.fPluginId
)
1527 # -------------------------------------------------------------
1530 self
.fButtonFont
= self
.ui
.b_gui
.font()
1531 self
.fButtonFont
.setBold(False)
1532 self
.fButtonFont
.setPixelSize(10)
1534 self
.fButtonColorOn
= QColor( 18, 41, 87)
1535 self
.fButtonColorOff
= QColor(150, 150, 150)
1537 # -------------------------------------------------------------
1540 self
.ui
.label_active
.setFont(self
.fButtonFont
)
1542 self
.ui
.b_remove
.setPixmaps(":/bitmaps/button_calf1.png",
1543 ":/bitmaps/button_calf1_down.png",
1544 ":/bitmaps/button_calf1_hover.png")
1546 self
.ui
.b_edit
.setTopText(self
.tr("Edit"), self
.fButtonColorOn
, self
.fButtonFont
)
1547 self
.ui
.b_remove
.setTopText(self
.tr("Remove"), self
.fButtonColorOn
, self
.fButtonFont
)
1549 if self
.fPluginInfo
['hints'] & PLUGIN_HAS_CUSTOM_UI
:
1550 self
.ui
.b_gui
.setTopText(self
.tr("GUI"), self
.fButtonColorOn
, self
.fButtonFont
)
1552 self
.ui
.b_gui
.setTopText(self
.tr("GUI"), self
.fButtonColorOff
, self
.fButtonFont
)
1554 if audioCount
['ins'] == 0:
1555 self
.ui
.label_audio_in
.hide()
1557 if audioCount
['outs'] == 0:
1558 self
.ui
.label_audio_out
.hide()
1560 if midiCount
['ins'] == 0:
1561 self
.ui
.label_midi
.hide()
1562 self
.ui
.led_midi
.hide()
1564 if self
.fIdleTimerId
!= 0:
1565 self
.ui
.b_remove
.setEnabled(False)
1566 self
.ui
.b_remove
.setVisible(False)
1568 # -------------------------------------------------------------
1570 self
.b_enable
= self
.ui
.b_enable
1571 self
.b_gui
= self
.ui
.b_gui
1572 self
.b_edit
= self
.ui
.b_edit
1573 self
.b_remove
= self
.ui
.b_remove
1575 self
.label_name
= self
.ui
.label_name
1576 self
.led_midi
= self
.ui
.led_midi
1578 self
.peak_in
= self
.ui
.peak_in
1579 self
.peak_out
= self
.ui
.peak_out
1581 self
.w_knobs_left
= self
.ui
.w_knobs
1582 self
.spacer_knobs
= self
.ui
.layout_bottom
.itemAt(1).spacerItem()
1586 self
.ui
.led_midi
.setColor(self
.ui
.led_midi
.CALF
)
1588 # -----------------------------------------------------------------
1590 def getFixedHeight(self
):
1591 return 94 if max(self
.peak_in
.channelCount(), self
.peak_out
.channelCount()) < 2 else 106
1593 # -----------------------------------------------------------------
1595 def editDialogPluginHintsChanged(self
, pluginId
, hints
):
1596 if hints
& PLUGIN_HAS_CUSTOM_UI
:
1597 self
.ui
.b_gui
.setTopText(self
.tr("GUI"), self
.fButtonColorOn
, self
.fButtonFont
)
1599 self
.ui
.b_gui
.setTopText(self
.tr("GUI"), self
.fButtonColorOff
, self
.fButtonFont
)
1601 AbstractPluginSlot
.editDialogPluginHintsChanged(self
, pluginId
, hints
)
1603 # -----------------------------------------------------------------
1605 def paintEvent(self
, event
):
1606 isBlack
= bool(self
.fSkinStyle
== "calf_black")
1608 painter
= QPainter(self
)
1609 painter
.setBrush(Qt
.transparent
)
1611 painter
.setPen(QPen(QColor(20, 20, 20) if isBlack
else QColor(75, 86, 99), 1))
1612 painter
.drawRect(0, 1, self
.width()-1, self
.height()-3)
1614 painter
.setPen(QPen(QColor(45, 45, 45) if isBlack
else QColor(86, 99, 114), 1))
1615 painter
.drawLine(0, 0, self
.width(), 0)
1617 AbstractPluginSlot
.paintEvent(self
, event
)
1619 # ------------------------------------------------------------------------------------------------------------
1621 class PluginSlot_Classic(AbstractPluginSlot
):
1622 def __init__(self
, parent
, host
, pluginId
):
1623 AbstractPluginSlot
.__init
__(self
, parent
, host
, pluginId
, (0,0,0), "classic")
1624 self
.ui
= ui_carla_plugin_classic
.Ui_PluginWidget()
1625 self
.ui
.setupUi(self
)
1627 # -------------------------------------------------------------
1630 self
.fColorTop
= QColor(60, 60, 60)
1631 self
.fColorBottom
= QColor(47, 47, 47)
1632 self
.fColorSeprtr
= QColor(70, 70, 70)
1634 # -------------------------------------------------------------
1636 self
.b_enable
= self
.ui
.b_enable
1637 self
.b_gui
= self
.ui
.b_gui
1638 self
.b_edit
= self
.ui
.b_edit
1640 self
.label_name
= self
.ui
.label_name
1641 self
.led_control
= self
.ui
.led_control
1642 self
.led_midi
= self
.ui
.led_midi
1643 self
.led_audio_in
= self
.ui
.led_audio_in
1644 self
.led_audio_out
= self
.ui
.led_audio_out
1646 self
.peak_in
= self
.ui
.peak_in
1647 self
.peak_out
= self
.ui
.peak_out
1651 # -----------------------------------------------------------------
1653 def getFixedHeight(self
):
1656 # -----------------------------------------------------------------
1658 def paintEvent(self
, event
):
1659 painter
= QPainter(self
)
1662 areaX
= self
.ui
.area_right
.x()+7
1663 width
= self
.width()
1664 height
= self
.height()
1666 painter
.setPen(QPen(QColor(17, 17, 17), 1))
1667 painter
.setBrush(QColor(17, 17, 17))
1668 painter
.drawRect(0, 0, width
, height
)
1670 painter
.setPen(self
.fColorSeprtr
.lighter(110))
1671 painter
.setBrush(self
.fColorBottom
)
1672 painter
.setRenderHint(QPainter
.Antialiasing
, True)
1675 path
= QPainterPath()
1676 path
.moveTo(areaX
-20, height
-4)
1677 path
.cubicTo(areaX
, height
-5, areaX
-20, 4.75, areaX
, 4.75)
1678 path
.lineTo(areaX
, height
-5)
1679 painter
.drawPath(path
)
1681 painter
.setPen(self
.fColorSeprtr
)
1682 painter
.setRenderHint(QPainter
.Antialiasing
, False)
1685 painter
.drawLine(0, height
-5, areaX
-20, height
-5)
1686 painter
.drawLine(areaX
, 4, width
, 4)
1688 painter
.setPen(self
.fColorBottom
)
1689 painter
.setBrush(self
.fColorBottom
)
1691 # top, bottom and left lines
1692 painter
.drawLine(0, 0, width
, 0)
1693 painter
.drawRect(0, height
-4, areaX
, 4)
1694 painter
.drawRoundedRect(areaX
-20, height
-5, areaX
, 5, 22, 22)
1695 painter
.drawLine(0, 0, 0, height
)
1698 painter
.drawRect(areaX
-1, 5, width
, height
)
1701 painter
.setPen(self
.fColorSeprtr
)
1702 painter
.drawLine(0, height
-1, width
, height
-1)
1705 AbstractPluginSlot
.paintEvent(self
, event
)
1707 # ------------------------------------------------------------------------------------------------------------
1709 class PluginSlot_Compact(AbstractPluginSlot
):
1710 def __init__(self
, parent
, host
, pluginId
, skinColor
, skinStyle
):
1711 AbstractPluginSlot
.__init
__(self
, parent
, host
, pluginId
, skinColor
, skinStyle
)
1712 self
.ui
= ui_carla_plugin_compact
.Ui_PluginWidget()
1713 self
.ui
.setupUi(self
)
1715 self
.b_enable
= self
.ui
.b_enable
1716 self
.b_gui
= self
.ui
.b_gui
1717 self
.b_edit
= self
.ui
.b_edit
1719 self
.label_name
= self
.ui
.label_name
1721 self
.led_control
= self
.ui
.led_control
1722 self
.led_midi
= self
.ui
.led_midi
1723 self
.led_audio_in
= self
.ui
.led_audio_in
1724 self
.led_audio_out
= self
.ui
.led_audio_out
1726 self
.peak_in
= self
.ui
.peak_in
1727 self
.peak_out
= self
.ui
.peak_out
1731 # -----------------------------------------------------------------
1733 def getFixedHeight(self
):
1734 if self
.fSkinStyle
== "calf_blue":
1738 # ------------------------------------------------------------------------------------------------------------
1740 class PluginSlot_Default(AbstractPluginSlot
):
1741 def __init__(self
, parent
, host
, pluginId
, skinColor
, skinStyle
):
1742 AbstractPluginSlot
.__init
__(self
, parent
, host
, pluginId
, skinColor
, skinStyle
)
1743 self
.ui
= ui_carla_plugin_default
.Ui_PluginWidget()
1744 self
.ui
.setupUi(self
)
1746 # -------------------------------------------------------------
1748 self
.b_enable
= self
.ui
.b_enable
1749 self
.b_gui
= self
.ui
.b_gui
1750 self
.b_edit
= self
.ui
.b_edit
1752 self
.label_name
= self
.ui
.label_name
1754 self
.led_control
= self
.ui
.led_control
1755 self
.led_midi
= self
.ui
.led_midi
1756 self
.led_audio_in
= self
.ui
.led_audio_in
1757 self
.led_audio_out
= self
.ui
.led_audio_out
1759 self
.peak_in
= self
.ui
.peak_in
1760 self
.peak_out
= self
.ui
.peak_out
1762 self
.w_knobs_left
= self
.ui
.w_knobs_left
1763 self
.w_knobs_right
= self
.ui
.w_knobs_right
1764 self
.spacer_knobs
= self
.ui
.layout_bottom
.itemAt(1).spacerItem()
1768 # -----------------------------------------------------------------
1770 def getFixedHeight(self
):
1773 # -----------------------------------------------------------------
1775 def paintEvent(self
, event
):
1776 painter
= QPainter(self
)
1777 painter
.setBrush(Qt
.transparent
)
1779 painter
.setPen(QPen(QColor(42, 42, 42), 1))
1780 painter
.drawRect(0, 1, self
.width()-1, self
.getFixedHeight()-3)
1782 painter
.setPen(QPen(QColor(60, 60, 60), 1))
1783 painter
.drawLine(0, 0, self
.width(), 0)
1785 AbstractPluginSlot
.paintEvent(self
, event
)
1787 # ------------------------------------------------------------------------------------------------------------
1789 class PluginSlot_Presets(AbstractPluginSlot
):
1790 def __init__(self
, parent
, host
, pluginId
, skinColor
, skinStyle
):
1791 AbstractPluginSlot
.__init
__(self
, parent
, host
, pluginId
, skinColor
, skinStyle
)
1792 self
.ui
= ui_carla_plugin_presets
.Ui_PluginWidget()
1793 self
.ui
.setupUi(self
)
1795 usingMidiPrograms
= bool(skinStyle
!= "presets")
1797 # -------------------------------------------------------------
1800 if usingMidiPrograms
:
1801 programCount
= self
.host
.get_midi_program_count(self
.fPluginId
)
1803 programCount
= self
.host
.get_program_count(self
.fPluginId
)
1805 if programCount
> 0:
1806 self
.ui
.cb_presets
.setEnabled(True)
1807 self
.ui
.label_presets
.setEnabled(True)
1809 for i
in range(programCount
):
1810 if usingMidiPrograms
:
1811 progName
= self
.host
.get_midi_program_data(self
.fPluginId
, i
)['name']
1813 progName
= self
.host
.get_program_name(self
.fPluginId
, i
)
1815 self
.ui
.cb_presets
.addItem(progName
)
1817 if usingMidiPrograms
:
1818 curProg
= self
.host
.get_current_midi_program_index(self
.fPluginId
)
1820 curProg
= self
.host
.get_current_program_index(self
.fPluginId
)
1822 self
.ui
.cb_presets
.setCurrentIndex(curProg
)
1825 self
.ui
.cb_presets
.setEnabled(False)
1826 self
.ui
.cb_presets
.setVisible(False)
1827 self
.ui
.label_presets
.setEnabled(False)
1828 self
.ui
.label_presets
.setVisible(False)
1830 # -------------------------------------------------------------
1832 self
.b_enable
= self
.ui
.b_enable
1833 self
.b_gui
= self
.ui
.b_gui
1834 self
.b_edit
= self
.ui
.b_edit
1836 self
.cb_presets
= self
.ui
.cb_presets
1838 self
.label_name
= self
.ui
.label_name
1839 self
.label_presets
= self
.ui
.label_presets
1841 self
.led_control
= self
.ui
.led_control
1842 self
.led_midi
= self
.ui
.led_midi
1843 self
.led_audio_in
= self
.ui
.led_audio_in
1844 self
.led_audio_out
= self
.ui
.led_audio_out
1846 self
.peak_in
= self
.ui
.peak_in
1847 self
.peak_out
= self
.ui
.peak_out
1849 if skinStyle
== "zynfx":
1850 self
.setupZynFxParams()
1852 self
.w_knobs_left
= self
.ui
.w_knobs_left
1853 self
.w_knobs_right
= self
.ui
.w_knobs_right
1854 self
.spacer_knobs
= self
.ui
.layout_bottom
.itemAt(1).spacerItem()
1858 if usingMidiPrograms
:
1859 self
.ui
.cb_presets
.currentIndexChanged
.connect(self
.slot_midiProgramChanged
)
1861 self
.ui
.cb_presets
.currentIndexChanged
.connect(self
.slot_programChanged
)
1863 # -------------------------------------------------------------
1865 def setupZynFxParams(self
):
1866 parameterCount
= min(self
.host
.get_parameter_count(self
.fPluginId
), 8)
1868 for i
in range(parameterCount
):
1869 paramInfo
= self
.host
.get_parameter_info(self
.fPluginId
, i
)
1870 paramData
= self
.host
.get_parameter_data(self
.fPluginId
, i
)
1871 paramRanges
= self
.host
.get_parameter_ranges(self
.fPluginId
, i
)
1873 if paramData
['type'] != PARAMETER_INPUT
:
1875 if paramData
['hints'] & PARAMETER_IS_BOOLEAN
:
1877 if (paramData
['hints'] & PARAMETER_IS_ENABLED
) == 0:
1880 paramName
= paramInfo
['name']
1882 if paramName
.startswith("unused"):
1885 # real zyn fx plugins
1886 if self
.fPluginInfo
['label'] == "zynalienwah":
1887 if i
== 0: paramName
= "Freq"
1888 elif i
== 1: paramName
= "Rnd"
1889 elif i
== 2: paramName
= "L type" # combobox
1890 elif i
== 3: paramName
= "St.df"
1891 elif i
== 5: paramName
= "Fb"
1892 elif i
== 7: paramName
= "L/R"
1894 elif self
.fPluginInfo
['label'] == "zynchorus":
1895 if i
== 0: paramName
= "Freq"
1896 elif i
== 1: paramName
= "Rnd"
1897 elif i
== 2: paramName
= "L type" # combobox
1898 elif i
== 3: paramName
= "St.df"
1899 elif i
== 6: paramName
= "Fb"
1900 elif i
== 7: paramName
= "L/R"
1901 elif i
== 8: paramName
= "Flngr" # button
1902 elif i
== 9: paramName
= "Subst" # button
1904 elif self
.fPluginInfo
['label'] == "zyndistortion":
1905 if i
== 0: paramName
= "LRc."
1906 elif i
== 4: paramName
= "Neg." # button
1907 elif i
== 5: paramName
= "LPF"
1908 elif i
== 6: paramName
= "HPF"
1909 elif i
== 7: paramName
= "St." # button
1910 elif i
== 8: paramName
= "PF" # button
1912 elif self
.fPluginInfo
['label'] == "zyndynamicfilter":
1913 if i
== 0: paramName
= "Freq"
1914 elif i
== 1: paramName
= "Rnd"
1915 elif i
== 2: paramName
= "L type" # combobox
1916 elif i
== 3: paramName
= "St.df"
1917 elif i
== 4: paramName
= "LfoD"
1918 elif i
== 5: paramName
= "A.S."
1919 elif i
== 6: paramName
= "A.Inv." # button
1920 elif i
== 7: paramName
= "A.M."
1922 elif self
.fPluginInfo
['label'] == "zynecho":
1923 if i
== 1: paramName
= "LRdl."
1924 elif i
== 2: paramName
= "LRc."
1925 elif i
== 3: paramName
= "Fb."
1926 elif i
== 4: paramName
= "Damp"
1928 elif self
.fPluginInfo
['label'] == "zynphaser":
1929 if i
== 0: paramName
= "Freq"
1930 elif i
== 1: paramName
= "Rnd"
1931 elif i
== 2: paramName
= "L type" # combobox
1932 elif i
== 3: paramName
= "St.df"
1933 elif i
== 5: paramName
= "Fb"
1934 elif i
== 7: paramName
= "L/R"
1935 elif i
== 8: paramName
= "Subst" # button
1936 elif i
== 9: paramName
= "Phase"
1937 elif i
== 11: paramName
= "Dist"
1939 elif self
.fPluginInfo
['label'] == "zynreverb":
1940 if i
== 2: paramName
= "I.delfb"
1941 elif i
== 5: paramName
= "LPF"
1942 elif i
== 6: paramName
= "HPF"
1943 elif i
== 9: paramName
= "R.S."
1944 elif i
== 10: paramName
= "I.del"
1947 paramName
= getParameterShortName(paramName
)
1949 widget
= ScalableDial(self
, i
)
1951 widget
.setLabel(paramName
)
1952 widget
.setMinimum(paramRanges
['min'])
1953 widget
.setMaximum(paramRanges
['max'])
1955 widget
.setCustomPaintColor(QColor(83, 173, 10))
1956 widget
.setCustomPaintMode(ScalableDial
.CUSTOM_PAINT_MODE_COLOR
)
1957 widget
.forceWhiteLabelGradientText()
1960 if (paramData
['hints'] & PARAMETER_IS_ENABLED
) == 0:
1961 widget
.setEnabled(False)
1963 self
.fParameterList
.append([i
, widget
])
1964 self
.ui
.w_knobs_left
.layout().addWidget(widget
)
1966 if self
.fPluginInfo
['hints'] & PLUGIN_CAN_DRYWET
:
1967 widget
= ScalableDial(self
, PARAMETER_DRYWET
)
1968 widget
.setLabel("Wet")
1969 widget
.setMinimum(0.0)
1970 widget
.setMaximum(1.0)
1972 widget
.setCustomPaintMode(ScalableDial
.CUSTOM_PAINT_MODE_CARLA_WET
)
1973 widget
.forceWhiteLabelGradientText()
1975 self
.fParameterList
.append([PARAMETER_DRYWET
, widget
])
1976 self
.ui
.w_knobs_right
.layout().addWidget(widget
)
1978 if self
.fPluginInfo
['hints'] & PLUGIN_CAN_VOLUME
:
1979 widget
= ScalableDial(self
, PARAMETER_VOLUME
)
1980 widget
.setLabel("Volume")
1981 widget
.setMinimum(0.0)
1982 widget
.setMaximum(1.27)
1984 widget
.setCustomPaintMode(ScalableDial
.CUSTOM_PAINT_MODE_CARLA_VOL
)
1985 widget
.forceWhiteLabelGradientText()
1987 self
.fParameterList
.append([PARAMETER_VOLUME
, widget
])
1988 self
.ui
.w_knobs_right
.layout().addWidget(widget
)
1990 # -----------------------------------------------------------------
1992 def getFixedHeight(self
):
1995 # -----------------------------------------------------------------
1997 def paintEvent(self
, event
):
1998 painter
= QPainter(self
)
1999 painter
.setBrush(Qt
.transparent
)
2001 painter
.setPen(QPen(QColor(50, 50, 50), 1))
2002 painter
.drawRect(0, 1, self
.width()-1, self
.height()-3)
2004 painter
.setPen(QPen(QColor(64, 64, 64), 1))
2005 painter
.drawLine(0, 0, self
.width(), 0)
2007 AbstractPluginSlot
.paintEvent(self
, event
)
2009 # ------------------------------------------------------------------------------------------------------------
2011 def getColorAndSkinStyle(host
, pluginId
):
2012 pluginInfo
= host
.get_plugin_info(pluginId
)
2013 pluginName
= host
.get_real_plugin_name(pluginId
)
2014 pluginLabel
= pluginInfo
['label'].lower()
2015 pluginMaker
= pluginInfo
['maker']
2016 uniqueId
= pluginInfo
['uniqueId']
2018 if pluginInfo
['type'] in (PLUGIN_VST2
, PLUGIN_VST3
, PLUGIN_AU
):
2019 progCount
= host
.get_program_count(pluginId
)
2021 progCount
= host
.get_midi_program_count(pluginId
)
2023 colorCategory
= getColorFromCategory(pluginInfo
['category'])
2027 if pluginInfo
['type'] == PLUGIN_SF2
:
2028 return (colorCategory
, "sf2")
2029 if pluginInfo
['type'] == PLUGIN_SFZ
:
2030 return (colorCategory
, "sfz")
2033 if pluginName
.split(" ", 1)[0].lower() == "calf":
2034 return (colorNone
, "calf_black" if "mono" in pluginLabel
else "calf_blue")
2037 if pluginMaker
== "OpenAV Productions":
2038 return (colorNone
, "openav-old")
2039 if pluginMaker
== "OpenAV":
2040 return (colorNone
, "openav")
2043 if pluginInfo
['type'] == PLUGIN_INTERNAL
:
2044 if pluginLabel
.startswith("zyn") and pluginInfo
['category'] != PLUGIN_CATEGORY_SYNTH
:
2045 return (colorNone
, "zynfx")
2047 if pluginInfo
['type'] == PLUGIN_LADSPA
:
2048 if pluginLabel
.startswith("zyn") and pluginMaker
.startswith("Josep Andreu"):
2049 return (colorNone
, "zynfx")
2051 if pluginInfo
['type'] == PLUGIN_LV2
:
2052 if pluginLabel
.startswith("http://kxstudio.sf.net/carla/plugins/zyn") and pluginName
!= "ZynAddSubFX":
2053 return (colorNone
, "zynfx")
2056 if progCount
> 1 and (pluginInfo
['hints'] & PLUGIN_USES_MULTI_PROGS
) == 0:
2057 if pluginInfo
['type'] in (PLUGIN_VST2
, PLUGIN_VST3
, PLUGIN_AU
):
2058 return (colorCategory
, "presets")
2059 return (colorCategory
, "mpresets")
2061 # DISTRHO Plugins (needs to be last)
2062 if pluginMaker
.startswith("falkTX, ") or pluginMaker
== "DISTRHO" or pluginLabel
.startswith("http://distrho.sf.net/plugins/"):
2063 skinStyle
= pluginLabel
.replace("http://distrho.sf.net/plugins/","")
2064 if skinStyle
in ("3bandeq", "nekobi"):
2065 return (colorNone
, skinStyle
)
2067 return (colorCategory
, "default")
2069 def createPluginSlot(parent
, host
, pluginId
, options
):
2070 skinColor
, skinStyle
= getColorAndSkinStyle(host
, pluginId
)
2072 if options
['color'] is not None:
2073 skinColor
= options
['color']
2076 skinStyle
= options
['skin']
2078 if skinStyle
== "classic":
2079 return PluginSlot_Classic(parent
, host
, pluginId
)
2081 if "compact" in skinStyle
or options
['compact']:
2082 return PluginSlot_Compact(parent
, host
, pluginId
, skinColor
, skinStyle
)
2084 if skinStyle
.startswith("calf"):
2085 return PluginSlot_Calf(parent
, host
, pluginId
, skinColor
, skinStyle
)
2087 if skinStyle
in ("mpresets", "presets", "zynfx"):
2088 return PluginSlot_Presets(parent
, host
, pluginId
, skinColor
, skinStyle
)
2090 return PluginSlot_Default(parent
, host
, pluginId
, skinColor
, skinStyle
)
2092 # ------------------------------------------------------------------------------------------------------------
2095 if __name__
== '__main__':
2096 from carla_app
import CarlaApplication
2097 from carla_host
import initHost
, loadHostSettings
2100 app
= CarlaApplication("Carla-Skins")
2101 host
= initHost("Skins", None, False, False, False)
2102 loadHostSettings(host
)
2104 host
.engine_init("JACK", "Carla-Widgets")
2105 host
.add_plugin(BINARY_NATIVE
, PLUGIN_INTERNAL
, "", "", "zynreverb", 0, None, PLUGIN_OPTIONS_NULL
)
2106 #host.add_plugin(BINARY_NATIVE, PLUGIN_DSSI, "/usr/lib/dssi/karplong.so", "karplong", "karplong", 0, None, PLUGIN_OPTIONS_NULL)
2107 #host.add_plugin(BINARY_NATIVE, PLUGIN_LV2, "", "", "http://www.openavproductions.com/sorcer", 0, None, PLUGIN_OPTIONS_NULL)
2108 #host.add_plugin(BINARY_NATIVE, PLUGIN_LV2, "", "", "http://calf.sourceforge.net/plugins/Compressor", 0, None, PLUGIN_OPTIONS_NULL)
2109 host
.set_active(0, True)
2111 #gui = createPluginSlot(None, host, 0, True)
2112 gui
= PluginSlot_Compact(None, host
, 0, (0, 0, 0), "default")