Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

carla_skin.py 79KB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
Rack enhancements 2 (#770) Squashed commit of the following: commit 0449cd63f7c356684903f784be434191df9c4392 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:19:23 2018 +0500 carla skin: fancy item selection commit 84a7b527a7eb79de1da215d6350ba5c639a46477 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:10:49 2018 +0500 carla skin: drawOutline: fixed positioning and optimization commit 30681d1523d088a728ba702c3af42ef97da2ddd2 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 01:20:53 2018 +0500 carla skin: drawOutline: set brush only once commit 63d2ab2e2189efdfa1c5e57b1519706184aa14bc Author: Nikita Zlobin <nick87720z@gmail.com> Date: Thu Oct 4 00:10:39 2018 +0500 carla skin: more neat QColor to tuple conversion commit 2137b781093177891d43bcf84cbcca9f7a398ba6 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 3 16:35:48 2018 +0500 rack item: Skin-independent colorization support Color menu item tints background color, preserving all visible relief. No need to lock it for some skins. commit 13fa4f2c34f789c43fa54c6657bb3dd018fcac80 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 15:00:58 2018 +0500 rack list: Colorized padding commit 9964af199453ce45ae8a8c10828a79d11870e011 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 17:48:17 2018 +0500 rack list: Colorized rails commit d212577057c5a914f52fd38a9d35645517e09d46 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 14:12:36 2018 +0500 rack list: Set frame in ui form commit 9a7e06098899ea5ac7e510b4374e3f88aeae8282 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 18:44:49 2018 +0500 rack list: Set common frame
6 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
Rack enhancements 2 (#770) Squashed commit of the following: commit 0449cd63f7c356684903f784be434191df9c4392 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:19:23 2018 +0500 carla skin: fancy item selection commit 84a7b527a7eb79de1da215d6350ba5c639a46477 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:10:49 2018 +0500 carla skin: drawOutline: fixed positioning and optimization commit 30681d1523d088a728ba702c3af42ef97da2ddd2 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 01:20:53 2018 +0500 carla skin: drawOutline: set brush only once commit 63d2ab2e2189efdfa1c5e57b1519706184aa14bc Author: Nikita Zlobin <nick87720z@gmail.com> Date: Thu Oct 4 00:10:39 2018 +0500 carla skin: more neat QColor to tuple conversion commit 2137b781093177891d43bcf84cbcca9f7a398ba6 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 3 16:35:48 2018 +0500 rack item: Skin-independent colorization support Color menu item tints background color, preserving all visible relief. No need to lock it for some skins. commit 13fa4f2c34f789c43fa54c6657bb3dd018fcac80 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 15:00:58 2018 +0500 rack list: Colorized padding commit 9964af199453ce45ae8a8c10828a79d11870e011 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 17:48:17 2018 +0500 rack list: Colorized rails commit d212577057c5a914f52fd38a9d35645517e09d46 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 14:12:36 2018 +0500 rack list: Set frame in ui form commit 9a7e06098899ea5ac7e510b4374e3f88aeae8282 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 18:44:49 2018 +0500 rack list: Set common frame
6 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
Rack enhancements 2 (#770) Squashed commit of the following: commit 0449cd63f7c356684903f784be434191df9c4392 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:19:23 2018 +0500 carla skin: fancy item selection commit 84a7b527a7eb79de1da215d6350ba5c639a46477 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:10:49 2018 +0500 carla skin: drawOutline: fixed positioning and optimization commit 30681d1523d088a728ba702c3af42ef97da2ddd2 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 01:20:53 2018 +0500 carla skin: drawOutline: set brush only once commit 63d2ab2e2189efdfa1c5e57b1519706184aa14bc Author: Nikita Zlobin <nick87720z@gmail.com> Date: Thu Oct 4 00:10:39 2018 +0500 carla skin: more neat QColor to tuple conversion commit 2137b781093177891d43bcf84cbcca9f7a398ba6 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 3 16:35:48 2018 +0500 rack item: Skin-independent colorization support Color menu item tints background color, preserving all visible relief. No need to lock it for some skins. commit 13fa4f2c34f789c43fa54c6657bb3dd018fcac80 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 15:00:58 2018 +0500 rack list: Colorized padding commit 9964af199453ce45ae8a8c10828a79d11870e011 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 17:48:17 2018 +0500 rack list: Colorized rails commit d212577057c5a914f52fd38a9d35645517e09d46 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 14:12:36 2018 +0500 rack list: Set frame in ui form commit 9a7e06098899ea5ac7e510b4374e3f88aeae8282 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 18:44:49 2018 +0500 rack list: Set common frame
6 years ago
Rack enhancements 2 (#770) Squashed commit of the following: commit 0449cd63f7c356684903f784be434191df9c4392 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:19:23 2018 +0500 carla skin: fancy item selection commit 84a7b527a7eb79de1da215d6350ba5c639a46477 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:10:49 2018 +0500 carla skin: drawOutline: fixed positioning and optimization commit 30681d1523d088a728ba702c3af42ef97da2ddd2 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 01:20:53 2018 +0500 carla skin: drawOutline: set brush only once commit 63d2ab2e2189efdfa1c5e57b1519706184aa14bc Author: Nikita Zlobin <nick87720z@gmail.com> Date: Thu Oct 4 00:10:39 2018 +0500 carla skin: more neat QColor to tuple conversion commit 2137b781093177891d43bcf84cbcca9f7a398ba6 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 3 16:35:48 2018 +0500 rack item: Skin-independent colorization support Color menu item tints background color, preserving all visible relief. No need to lock it for some skins. commit 13fa4f2c34f789c43fa54c6657bb3dd018fcac80 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 15:00:58 2018 +0500 rack list: Colorized padding commit 9964af199453ce45ae8a8c10828a79d11870e011 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 17:48:17 2018 +0500 rack list: Colorized rails commit d212577057c5a914f52fd38a9d35645517e09d46 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 14:12:36 2018 +0500 rack list: Set frame in ui form commit 9a7e06098899ea5ac7e510b4374e3f88aeae8282 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 18:44:49 2018 +0500 rack list: Set common frame
6 years ago
Rack enhancements 2 (#770) Squashed commit of the following: commit 0449cd63f7c356684903f784be434191df9c4392 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:19:23 2018 +0500 carla skin: fancy item selection commit 84a7b527a7eb79de1da215d6350ba5c639a46477 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:10:49 2018 +0500 carla skin: drawOutline: fixed positioning and optimization commit 30681d1523d088a728ba702c3af42ef97da2ddd2 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 01:20:53 2018 +0500 carla skin: drawOutline: set brush only once commit 63d2ab2e2189efdfa1c5e57b1519706184aa14bc Author: Nikita Zlobin <nick87720z@gmail.com> Date: Thu Oct 4 00:10:39 2018 +0500 carla skin: more neat QColor to tuple conversion commit 2137b781093177891d43bcf84cbcca9f7a398ba6 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 3 16:35:48 2018 +0500 rack item: Skin-independent colorization support Color menu item tints background color, preserving all visible relief. No need to lock it for some skins. commit 13fa4f2c34f789c43fa54c6657bb3dd018fcac80 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 15:00:58 2018 +0500 rack list: Colorized padding commit 9964af199453ce45ae8a8c10828a79d11870e011 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 17:48:17 2018 +0500 rack list: Colorized rails commit d212577057c5a914f52fd38a9d35645517e09d46 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 14:12:36 2018 +0500 rack list: Set frame in ui form commit 9a7e06098899ea5ac7e510b4374e3f88aeae8282 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 18:44:49 2018 +0500 rack list: Set common frame
6 years ago
Rack enhancements 2 (#770) Squashed commit of the following: commit 0449cd63f7c356684903f784be434191df9c4392 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:19:23 2018 +0500 carla skin: fancy item selection commit 84a7b527a7eb79de1da215d6350ba5c639a46477 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 02:10:49 2018 +0500 carla skin: drawOutline: fixed positioning and optimization commit 30681d1523d088a728ba702c3af42ef97da2ddd2 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Oct 5 01:20:53 2018 +0500 carla skin: drawOutline: set brush only once commit 63d2ab2e2189efdfa1c5e57b1519706184aa14bc Author: Nikita Zlobin <nick87720z@gmail.com> Date: Thu Oct 4 00:10:39 2018 +0500 carla skin: more neat QColor to tuple conversion commit 2137b781093177891d43bcf84cbcca9f7a398ba6 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 3 16:35:48 2018 +0500 rack item: Skin-independent colorization support Color menu item tints background color, preserving all visible relief. No need to lock it for some skins. commit 13fa4f2c34f789c43fa54c6657bb3dd018fcac80 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 15:00:58 2018 +0500 rack list: Colorized padding commit 9964af199453ce45ae8a8c10828a79d11870e011 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 17:48:17 2018 +0500 rack list: Colorized rails commit d212577057c5a914f52fd38a9d35645517e09d46 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Wed Oct 10 14:12:36 2018 +0500 rack list: Set frame in ui form commit 9a7e06098899ea5ac7e510b4374e3f88aeae8282 Author: Nikita Zlobin <nick87720z@gmail.com> Date: Fri Sep 28 18:44:49 2018 +0500 rack list: Set common frame
6 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
9 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla plugin/slot skin code
  4. # Copyright (C) 2013-2020 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation; either version 2 of
  9. # the License, or any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. from PyQt5.QtCore import Qt, QRectF, QLineF, QTimer
  20. from PyQt5.QtGui import QColor, QFont, QFontDatabase, QPainter, QPainterPath, QPen
  21. from PyQt5.QtWidgets import QColorDialog, QFrame, QLineEdit, QPushButton
  22. # ------------------------------------------------------------------------------------------------------------
  23. # Imports (Custom)
  24. import ui_carla_plugin_calf
  25. import ui_carla_plugin_classic
  26. import ui_carla_plugin_compact
  27. import ui_carla_plugin_default
  28. import ui_carla_plugin_presets
  29. from carla_backend import *
  30. from carla_shared import *
  31. from carla_widgets import *
  32. from widgets.digitalpeakmeter import DigitalPeakMeter
  33. from widgets.paramspinbox import CustomInputDialog
  34. from widgets.scalabledial import ScalableDial
  35. # ------------------------------------------------------------------------------------------------------------
  36. # Plugin Skin Rules (WORK IN PROGRESS)
  37. # Base is a QFrame (NoFrame, Plain, 0-size lines), with "PluginWidget" as object name.
  38. # Spacing of the top-most layout must be 1px.
  39. # Top and bottom margins must be 3px (can be split between different Qt layouts).
  40. # Left and right margins must be 6px (can be split between different Qt layouts).
  41. # If the left or right side has built-in margins, say a transparent svg border,
  42. # those margins must be taken into consideration.
  43. #
  44. # There's a top and bottom layout, separated by a horizontal line.
  45. # Compacted skins do not have the bottom layout and separating line.
  46. # T O P A R E A
  47. #
  48. # -----------------------------------------------------------------
  49. # | <> | <> [ WIDGETS ] [ LEDS ] |
  50. # | BUTTONS <> | <> PLUGIN NAME < spacer > [ WIDGETS ] [ LEDS ] |
  51. # | <> | <> [ WIDGETS ] [ LEDS ] |
  52. # -----------------------------------------------------------------
  53. #
  54. # Buttons area has size fixed. (TBA)
  55. # Spacers at the left of the plugin name must be 8x1 in size (fixed).
  56. # The line before the plugin name must be height-10px (fixed).
  57. # WIDGETS area can be extended to the left, if using meters they should have 80px.
  58. # WIDGETS margins are 4px for left+right and 2px for top+bottom, with 4px spacing.
  59. # ------------------------------------------------------------------------------------------------------------
  60. # Try to "shortify" a parameter name
  61. def getParameterShortName(paramName):
  62. paramName = paramName.split("/",1)[0].split(" (",1)[0].split(" [",1)[0].strip()
  63. paramLow = paramName.lower()
  64. # Cut useless prefix
  65. if paramLow.startswith("compressor "):
  66. paramName = paramName.replace("ompressor ", ".", 1)
  67. paramLow = paramName.lower()
  68. elif paramLow.startswith("room "):
  69. paramName = paramName.split(" ",1)[1]
  70. paramLow = paramName.lower()
  71. # Cut useless suffix
  72. if paramLow.endswith(" level"):
  73. paramName = paramName.rsplit(" ",1)[0]
  74. paramLow = paramName.lower()
  75. elif paramLow.endswith(" time"):
  76. paramName = paramName.rsplit(" ",1)[0]
  77. paramLow = paramName.lower()
  78. # Cut generic names
  79. if "attack" in paramLow:
  80. paramName = paramName.replace("ttack", "tk")
  81. elif "bandwidth" in paramLow:
  82. paramName = paramName.replace("andwidth", "w")
  83. elif "damping" in paramLow:
  84. paramName = paramName.replace("amping", "amp")
  85. elif "distortion" in paramLow:
  86. paramName = paramName.replace("istortion", "ist")
  87. elif "feedback" in paramLow:
  88. paramName = paramName.replace("eedback", "b")
  89. elif "frequency" in paramLow:
  90. paramName = paramName.replace("requency", "req")
  91. elif "input" in paramLow:
  92. paramName = paramName.replace("nput", "n")
  93. elif "makeup" in paramLow:
  94. paramName = paramName.replace("akeup", "kUp" if "Make" in paramName else "kup")
  95. elif "output" in paramLow:
  96. paramName = paramName.replace("utput", "ut")
  97. elif "random" in paramLow:
  98. paramName = paramName.replace("andom", "nd")
  99. elif "threshold" in paramLow:
  100. paramName = paramName.replace("hreshold", "hres")
  101. # remove space if last char from 1st word is lowercase and the first char from the 2nd is uppercase,
  102. # or if 2nd is a number
  103. if " " in paramName:
  104. name1, name2 = paramName.split(" ", 1)
  105. if (name1[-1].islower() and name2[0].isupper()) or name2.isdigit():
  106. paramName = paramName.replace(" ", "", 1)
  107. # cut stuff if too big
  108. if len(paramName) > 7:
  109. paramName = paramName.replace("a","").replace("e","").replace("i","").replace("o","").replace("u","")
  110. if len(paramName) > 7:
  111. paramName = paramName[:7]
  112. return paramName.strip()
  113. # ------------------------------------------------------------------------------------------------------------
  114. # Get RGB colors for a plugin category
  115. def getColorFromCategory(category):
  116. r = 40
  117. g = 40
  118. b = 40
  119. if category == PLUGIN_CATEGORY_MODULATOR:
  120. r += 10
  121. elif category == PLUGIN_CATEGORY_EQ:
  122. g += 10
  123. elif category == PLUGIN_CATEGORY_FILTER:
  124. b += 10
  125. elif category == PLUGIN_CATEGORY_DELAY:
  126. r += 15
  127. b -= 15
  128. elif category == PLUGIN_CATEGORY_DISTORTION:
  129. g += 10
  130. b += 10
  131. elif category == PLUGIN_CATEGORY_DYNAMICS:
  132. r += 10
  133. b += 10
  134. elif category == PLUGIN_CATEGORY_UTILITY:
  135. r += 10
  136. g += 10
  137. return (r, g, b)
  138. # ------------------------------------------------------------------------------------------------------------
  139. #
  140. def setScalableDialStyle(widget, parameterId, parameterCount, whiteLabels, skinStyle):
  141. if skinStyle.startswith("calf"):
  142. widget.setCustomPaintMode(ScalableDial.CUSTOM_PAINT_MODE_NO_GRADIENT)
  143. widget.setImage(7)
  144. elif skinStyle.startswith("openav"):
  145. widget.setCustomPaintMode(ScalableDial.CUSTOM_PAINT_MODE_NO_GRADIENT)
  146. if parameterId == PARAMETER_DRYWET:
  147. widget.setImage(13)
  148. elif parameterId == PARAMETER_VOLUME:
  149. widget.setImage(12)
  150. else:
  151. widget.setImage(11)
  152. else:
  153. if parameterId == PARAMETER_DRYWET:
  154. widget.setCustomPaintMode(ScalableDial.CUSTOM_PAINT_MODE_CARLA_WET)
  155. elif parameterId == PARAMETER_VOLUME:
  156. widget.setCustomPaintMode(ScalableDial.CUSTOM_PAINT_MODE_CARLA_VOL)
  157. else:
  158. _r = 255 - int((float(parameterId)/float(parameterCount))*200.0)
  159. _g = 55 + int((float(parameterId)/float(parameterCount))*200.0)
  160. _b = 0 #(r-40)*4
  161. widget.setCustomPaintColor(QColor(_r, _g, _b))
  162. widget.setCustomPaintMode(ScalableDial.CUSTOM_PAINT_MODE_COLOR)
  163. if whiteLabels:
  164. colorEnabled = QColor("#BBB")
  165. colorDisabled = QColor("#555")
  166. else:
  167. colorEnabled = QColor("#111")
  168. colorDisabled = QColor("#AAA")
  169. widget.setLabelColor(colorEnabled, colorDisabled)
  170. widget.setImage(3)
  171. # ------------------------------------------------------------------------------------------------------------
  172. # Abstract plugin slot
  173. class AbstractPluginSlot(QFrame, PluginEditParentMeta):
  174. def __init__(self, parent, host, pluginId, skinColor, skinStyle):
  175. QFrame.__init__(self, parent)
  176. self.host = host
  177. self.fParent = parent
  178. # -------------------------------------------------------------
  179. # Get plugin info
  180. self.fPluginId = pluginId
  181. self.fPluginInfo = host.get_plugin_info(self.fPluginId)
  182. self.fSkinColor = skinColor
  183. self.fSkinStyle = skinStyle
  184. self.fDarkStyle = QColor(skinColor[0], skinColor[1], skinColor[2]).blackF() > 0.4
  185. # -------------------------------------------------------------
  186. # Internal stuff
  187. self.fIsActive = False
  188. self.fIsSelected = False
  189. self.fLastGreenLedState = False
  190. self.fLastBlueLedState = False
  191. self.fParameterIconTimer = ICON_STATE_NULL
  192. self.fParameterList = [] # index, widget
  193. audioCountInfo = host.get_audio_port_count_info(self.fPluginId)
  194. self.fPeaksInputCount = audioCountInfo['ins']
  195. self.fPeaksOutputCount = audioCountInfo['outs']
  196. if self.fPeaksInputCount > 2:
  197. self.fPeaksInputCount = 2
  198. if self.fPeaksOutputCount > 2:
  199. self.fPeaksOutputCount = 2
  200. self.fAdjustViewableKnobCountScheduled = False
  201. # used during testing
  202. self.fIdleTimerId = 0
  203. # -------------------------------------------------------------
  204. # Set-up GUI
  205. self.fEditDialog = PluginEdit(self, host, self.fPluginId)
  206. # -------------------------------------------------------------
  207. # Set-up common widgets (as none)
  208. self.b_enable = None
  209. self.b_gui = None
  210. self.b_edit = None
  211. self.b_remove = None
  212. self.cb_presets = None
  213. self.label_name = None
  214. self.label_presets = None
  215. self.label_type = None
  216. self.led_control = None
  217. self.led_midi = None
  218. self.led_audio_in = None
  219. self.led_audio_out = None
  220. self.peak_in = None
  221. self.peak_out = None
  222. self.w_knobs_left = None
  223. self.w_knobs_right = None
  224. self.spacer_knobs = None
  225. # -------------------------------------------------------------
  226. # Set-up connections
  227. self.customContextMenuRequested.connect(self.slot_showCustomMenu)
  228. host.PluginRenamedCallback.connect(self.slot_handlePluginRenamedCallback)
  229. host.PluginUnavailableCallback.connect(self.slot_handlePluginUnavailableCallback)
  230. host.ParameterValueChangedCallback.connect(self.slot_handleParameterValueChangedCallback)
  231. host.ParameterDefaultChangedCallback.connect(self.slot_handleParameterDefaultChangedCallback)
  232. host.ParameterMappedControlIndexChangedCallback.connect(self.slot_handleParameterMappedControlIndexChangedCallback)
  233. host.ParameterMappedRangeChangedCallback.connect(self.slot_handleParameterMappedRangeChangedCallback)
  234. host.ParameterMidiChannelChangedCallback.connect(self.slot_handleParameterMidiChannelChangedCallback)
  235. host.ProgramChangedCallback.connect(self.slot_handleProgramChangedCallback)
  236. host.MidiProgramChangedCallback.connect(self.slot_handleMidiProgramChangedCallback)
  237. host.OptionChangedCallback.connect(self.slot_handleOptionChangedCallback)
  238. host.UiStateChangedCallback.connect(self.slot_handleUiStateChangedCallback)
  239. # Prepare resources
  240. self.sel_pen = QPen(Qt.cyan, 1, Qt.SolidLine, Qt.FlatCap, Qt.MiterJoin)
  241. self.sel_pen.setDashPattern([2.0, 4.0])
  242. self.sel_side_pen = QPen(Qt.cyan, 2, Qt.SolidLine, Qt.FlatCap)
  243. self.shadow_pen = QPen(Qt.black, 1)
  244. # -----------------------------------------------------------------
  245. @pyqtSlot(int, str)
  246. def slot_handlePluginRenamedCallback(self, pluginId, newName):
  247. if self.fEditDialog is not None and self.fPluginId == pluginId:
  248. self.setName(newName)
  249. @pyqtSlot(int, str)
  250. def slot_handlePluginUnavailableCallback(self, pluginId, errorMsg):
  251. if self.fEditDialog is not None and self.fPluginId == pluginId:
  252. pass
  253. @pyqtSlot(int, int, float)
  254. def slot_handleParameterValueChangedCallback(self, pluginId, index, value):
  255. if self.fEditDialog is not None and self.fPluginId == pluginId:
  256. self.setParameterValue(index, value, True)
  257. @pyqtSlot(int, int, float)
  258. def slot_handleParameterDefaultChangedCallback(self, pluginId, index, value):
  259. if self.fEditDialog is not None and self.fPluginId == pluginId:
  260. self.setParameterDefault(index, value)
  261. @pyqtSlot(int, int, int)
  262. def slot_handleParameterMappedControlIndexChangedCallback(self, pluginId, index, ctrl):
  263. if self.fEditDialog is not None and self.fPluginId == pluginId:
  264. self.setParameterMappedControlIndex(index, ctrl)
  265. @pyqtSlot(int, int, float, float)
  266. def slot_handleParameterMappedRangeChangedCallback(self, pluginId, index, minimum, maximum):
  267. if self.fEditDialog is not None and self.fPluginId == pluginId:
  268. self.setParameterMappedRange(index, minimum, maximum)
  269. @pyqtSlot(int, int, int)
  270. def slot_handleParameterMidiChannelChangedCallback(self, pluginId, index, channel):
  271. if self.fEditDialog is not None and self.fPluginId == pluginId:
  272. self.setParameterMidiChannel(index, channel)
  273. @pyqtSlot(int, int)
  274. def slot_handleProgramChangedCallback(self, pluginId, index):
  275. if self.fEditDialog is not None and self.fPluginId == pluginId:
  276. self.setProgram(index, True)
  277. @pyqtSlot(int, int)
  278. def slot_handleMidiProgramChangedCallback(self, pluginId, index):
  279. if self.fEditDialog is not None and self.fPluginId == pluginId:
  280. self.setMidiProgram(index, True)
  281. @pyqtSlot(int, int, bool)
  282. def slot_handleOptionChangedCallback(self, pluginId, option, yesNo):
  283. if self.fEditDialog is not None and self.fPluginId == pluginId:
  284. self.setOption(option, yesNo)
  285. @pyqtSlot(int, int)
  286. def slot_handleUiStateChangedCallback(self, pluginId, state):
  287. if self.fEditDialog is not None and self.fPluginId == pluginId:
  288. self.customUiStateChanged(state)
  289. # ------------------------------------------------------------------
  290. def ready(self):
  291. self.fIsActive = bool(self.host.get_internal_parameter_value(self.fPluginId, PARAMETER_ACTIVE) >= 0.5)
  292. isCalfSkin = self.fSkinStyle.startswith("calf") and not isinstance(self, PluginSlot_Compact)
  293. imageSuffix = "white" if self.fDarkStyle else "black"
  294. whiteLabels = self.fDarkStyle
  295. if self.fSkinStyle.startswith("calf") or self.fSkinStyle.startswith("openav") or self.fSkinStyle in (
  296. "3bandeq", "3bandsplitter", "pingpongpan", "nekobi", "calf_black", "zynfx"):
  297. imageSuffix = "white"
  298. whiteLabels = True
  299. if self.b_enable is not None:
  300. self.b_enable.setChecked(self.fIsActive)
  301. self.b_enable.clicked.connect(self.slot_enableClicked)
  302. if isCalfSkin:
  303. self.b_enable.setPixmaps(":/bitmaps/button_calf3.png",
  304. ":/bitmaps/button_calf3_down.png",
  305. ":/bitmaps/button_calf3.png")
  306. else:
  307. self.b_enable.setSvgs(":/scalable/button_off.svg",
  308. ":/scalable/button_on.svg",
  309. ":/scalable/button_off.svg")
  310. if self.b_gui is not None:
  311. self.b_gui.clicked.connect(self.slot_showCustomUi)
  312. self.b_gui.setEnabled(bool(self.fPluginInfo['hints'] & PLUGIN_HAS_CUSTOM_UI))
  313. if isCalfSkin:
  314. self.b_gui.setPixmaps(":/bitmaps/button_calf2.png",
  315. ":/bitmaps/button_calf2_down.png",
  316. ":/bitmaps/button_calf2_hover.png")
  317. elif self.fPluginInfo['iconName'] == "distrho" or self.fSkinStyle in ("3bandeq", "3bandsplitter", "pingpongpan", "nekobi"):
  318. self.b_gui.setPixmaps(":/bitmaps/button_distrho-{}.png".format(imageSuffix),
  319. ":/bitmaps/button_distrho_down-{}.png".format(imageSuffix),
  320. ":/bitmaps/button_distrho_hover-{}.png".format(imageSuffix))
  321. elif self.fPluginInfo['iconName'] == "file":
  322. self.b_gui.setPixmaps(":/bitmaps/button_file-{}.png".format(imageSuffix),
  323. ":/bitmaps/button_file_down-{}.png".format(imageSuffix),
  324. ":/bitmaps/button_file_hover-{}.png".format(imageSuffix))
  325. else:
  326. if imageSuffix == "black": # TODO
  327. self.b_gui.setPixmaps(":/bitmaps/button_gui-{}.png".format(imageSuffix),
  328. ":/bitmaps/button_gui_down-{}.png".format(imageSuffix),
  329. ":/bitmaps/button_gui_hover-{}.png".format(imageSuffix))
  330. else:
  331. self.b_gui.setSvgs(":/scalable/button_gui-{}.svg".format(imageSuffix),
  332. ":/scalable/button_gui_down-{}.svg".format(imageSuffix),
  333. ":/scalable/button_gui_hover-{}.svg".format(imageSuffix))
  334. if self.b_edit is not None:
  335. self.b_edit.clicked.connect(self.slot_showEditDialog)
  336. if isCalfSkin:
  337. self.b_edit.setPixmaps(":/bitmaps/button_calf2.png",
  338. ":/bitmaps/button_calf2_down.png",
  339. ":/bitmaps/button_calf2_hover.png")
  340. else:
  341. self.b_edit.setSvgs(":/scalable/button_edit-{}.svg".format(imageSuffix),
  342. ":/scalable/button_edit_down-{}.svg".format(imageSuffix),
  343. ":/scalable/button_edit_hover-{}.svg".format(imageSuffix))
  344. else:
  345. # Edit button *must* be available
  346. self.b_edit = QPushButton(self)
  347. self.b_edit.setCheckable(True)
  348. self.b_edit.hide()
  349. if self.b_remove is not None:
  350. self.b_remove.clicked.connect(self.slot_removePlugin)
  351. if self.label_name is not None:
  352. self.label_name.setEnabled(self.fIsActive)
  353. self.label_name.setText(self.fPluginInfo['name'])
  354. nameFont = self.label_name.font()
  355. if self.fSkinStyle.startswith("calf"):
  356. nameFont.setBold(True)
  357. nameFont.setPixelSize(12)
  358. elif self.fSkinStyle.startswith("openav"):
  359. QFontDatabase.addApplicationFont(":/fonts/uranium.ttf")
  360. nameFont.setFamily("Uranium")
  361. nameFont.setPixelSize(15)
  362. nameFont.setCapitalization(QFont.AllUppercase)
  363. else:
  364. nameFont.setBold(True)
  365. nameFont.setPixelSize(11)
  366. self.label_name.setFont(nameFont)
  367. if self.label_presets is not None:
  368. presetFont = self.label_presets.font()
  369. presetFont.setBold(True)
  370. presetFont.setPixelSize(10)
  371. self.label_presets.setFont(presetFont)
  372. if self.label_type is not None:
  373. self.label_type.setText(getPluginTypeAsString(self.fPluginInfo['type']))
  374. if self.led_control is not None:
  375. self.led_control.setColor(self.led_control.YELLOW)
  376. self.led_control.setEnabled(False)
  377. if self.led_midi is not None:
  378. self.led_midi.setColor(self.led_midi.RED)
  379. self.led_midi.setEnabled(False)
  380. if self.led_audio_in is not None:
  381. self.led_audio_in.setColor(self.led_audio_in.GREEN)
  382. self.led_audio_in.setEnabled(False)
  383. if self.led_audio_out is not None:
  384. self.led_audio_out.setColor(self.led_audio_out.BLUE)
  385. self.led_audio_out.setEnabled(False)
  386. if self.peak_in is not None:
  387. self.peak_in.setChannelCount(self.fPeaksInputCount)
  388. self.peak_in.setMeterColor(DigitalPeakMeter.COLOR_GREEN)
  389. self.peak_in.setMeterOrientation(DigitalPeakMeter.HORIZONTAL)
  390. if self.fSkinStyle.startswith("calf"):
  391. self.peak_in.setMeterStyle(DigitalPeakMeter.STYLE_CALF)
  392. elif self.fSkinStyle == "rncbc":
  393. self.peak_in.setMeterStyle(DigitalPeakMeter.STYLE_RNCBC)
  394. elif self.fSkinStyle.startswith("openav") or self.fSkinStyle == "zynfx":
  395. self.peak_in.setMeterStyle(DigitalPeakMeter.STYLE_OPENAV)
  396. if self.fPeaksInputCount == 0 and not isinstance(self, PluginSlot_Classic):
  397. self.peak_in.hide()
  398. if self.peak_out is not None:
  399. self.peak_out.setChannelCount(self.fPeaksOutputCount)
  400. self.peak_out.setMeterColor(DigitalPeakMeter.COLOR_BLUE)
  401. self.peak_out.setMeterOrientation(DigitalPeakMeter.HORIZONTAL)
  402. if self.fSkinStyle.startswith("calf"):
  403. self.peak_out.setMeterStyle(DigitalPeakMeter.STYLE_CALF)
  404. elif self.fSkinStyle == "rncbc":
  405. self.peak_out.setMeterStyle(DigitalPeakMeter.STYLE_RNCBC)
  406. elif self.fSkinStyle.startswith("openav") or self.fSkinStyle == "zynfx":
  407. self.peak_out.setMeterStyle(DigitalPeakMeter.STYLE_OPENAV)
  408. if self.fPeaksOutputCount == 0 and not isinstance(self, PluginSlot_Classic):
  409. self.peak_out.hide()
  410. # -------------------------------------------------------------
  411. if self.fSkinStyle == "openav":
  412. styleSheet = """
  413. QFrame#PluginWidget {
  414. background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
  415. stop: 0 #383838, stop: %f #111111, stop: 1.0 #111111);
  416. }
  417. QLabel#label_name { color: #FFFFFF; }
  418. QLabel#label_name:disabled { color: #505050; }
  419. """ % (0.95 if isinstance(self, PluginSlot_Compact) else 0.35)
  420. elif self.fSkinStyle == "openav-old":
  421. styleSheet = """
  422. QFrame#PluginWidget {
  423. background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
  424. stop: 0 #303030, stop: %f #111111, stop: 1.0 #111111);
  425. }
  426. QLabel#label_name { color: #FF5100; }
  427. QLabel#label_name:disabled { color: #505050; }
  428. """ % (0.95 if isinstance(self, PluginSlot_Compact) else 0.35)
  429. else:
  430. colorEnabled = "#BBB"
  431. colorDisabled = "#555"
  432. if self.fSkinStyle in ("3bandeq", "calf_black", "calf_blue", "nekobi", "zynfx"):
  433. styleSheet2 = "background-image: url(:/bitmaps/background_%s.png);" % self.fSkinStyle
  434. else:
  435. styleSheet2 = "background-color: rgb(200, 200, 200);"
  436. styleSheet2 += "background-image: url(:/bitmaps/background_noise1.png);"
  437. if not self.fDarkStyle:
  438. colorEnabled = "#111"
  439. colorDisabled = "#AAA"
  440. styleSheet = """
  441. QFrame#PluginWidget {
  442. %s
  443. background-repeat: repeat-xy;
  444. }
  445. QLabel#label_name,
  446. QLabel#label_audio_in,
  447. QLabel#label_audio_out,
  448. QLabel#label_midi,
  449. QLabel#label_presets { color: %s; }
  450. QLabel#label_name:disabled { color: %s; }
  451. """ % (styleSheet2, colorEnabled, colorDisabled)
  452. styleSheet += """
  453. QComboBox#cb_presets,
  454. QLabel#label_audio_in,
  455. QLabel#label_audio_out,
  456. QLabel#label_midi { font-size: 10px; }
  457. """
  458. self.setStyleSheet(styleSheet)
  459. # -------------------------------------------------------------
  460. # Set-up parameters
  461. if self.w_knobs_left is not None:
  462. parameterCount = self.host.get_parameter_count(self.fPluginId)
  463. index = 0
  464. layout = self.w_knobs_left.layout()
  465. for i in range(parameterCount):
  466. # 50 should be enough for everybody, right?
  467. if index >= 50:
  468. break
  469. paramInfo = self.host.get_parameter_info(self.fPluginId, i)
  470. paramData = self.host.get_parameter_data(self.fPluginId, i)
  471. paramRanges = self.host.get_parameter_ranges(self.fPluginId, i)
  472. isInteger = (paramData['hints'] & PARAMETER_IS_INTEGER) != 0
  473. if paramData['type'] != PARAMETER_INPUT:
  474. continue
  475. if paramData['hints'] & PARAMETER_IS_BOOLEAN:
  476. continue
  477. if (paramData['hints'] & PARAMETER_IS_ENABLED) == 0:
  478. continue
  479. if (paramData['hints'] & PARAMETER_USES_SCALEPOINTS) != 0 and not isInteger:
  480. # NOTE: we assume integer scalepoints are continuous
  481. continue
  482. if isInteger and paramRanges['max']-paramRanges['min'] <= 3:
  483. continue
  484. if paramInfo['name'].startswith("unused"):
  485. continue
  486. paramName = getParameterShortName(paramInfo['name'])
  487. widget = ScalableDial(self, i)
  488. widget.setLabel(paramName)
  489. widget.setMinimum(paramRanges['min'])
  490. widget.setMaximum(paramRanges['max'])
  491. widget.hide()
  492. if isInteger:
  493. widget.setPrecision(paramRanges['max']-paramRanges['min'], True)
  494. setScalableDialStyle(widget, i, parameterCount, whiteLabels, self.fSkinStyle)
  495. index += 1
  496. self.fParameterList.append([i, widget])
  497. layout.addWidget(widget)
  498. if self.w_knobs_right is not None and (self.fPluginInfo['hints'] & PLUGIN_CAN_DRYWET) != 0:
  499. widget = ScalableDial(self, PARAMETER_DRYWET)
  500. widget.setLabel("Dry/Wet")
  501. widget.setMinimum(0.0)
  502. widget.setMaximum(1.0)
  503. setScalableDialStyle(widget, PARAMETER_DRYWET, 0, whiteLabels, self.fSkinStyle)
  504. self.fParameterList.append([PARAMETER_DRYWET, widget])
  505. self.w_knobs_right.layout().addWidget(widget)
  506. if self.w_knobs_right is not None and (self.fPluginInfo['hints'] & PLUGIN_CAN_VOLUME) != 0:
  507. widget = ScalableDial(self, PARAMETER_VOLUME)
  508. widget.setLabel("Volume")
  509. widget.setMinimum(0.0)
  510. widget.setMaximum(1.27)
  511. setScalableDialStyle(widget, PARAMETER_VOLUME, 0, whiteLabels, self.fSkinStyle)
  512. self.fParameterList.append([PARAMETER_VOLUME, widget])
  513. self.w_knobs_right.layout().addWidget(widget)
  514. for paramIndex, paramWidget in self.fParameterList:
  515. paramWidget.setContextMenuPolicy(Qt.CustomContextMenu)
  516. paramWidget.customContextMenuRequested.connect(self.slot_knobCustomMenu)
  517. paramWidget.dragStateChanged.connect(self.slot_parameterDragStateChanged)
  518. paramWidget.realValueChanged.connect(self.slot_parameterValueChanged)
  519. paramWidget.blockSignals(True)
  520. paramWidget.setValue(self.host.get_internal_parameter_value(self.fPluginId, paramIndex))
  521. paramWidget.blockSignals(False)
  522. # -------------------------------------------------------------
  523. self.setWindowTitle(self.fPluginInfo['name'])
  524. if not self.fAdjustViewableKnobCountScheduled:
  525. self.fAdjustViewableKnobCountScheduled = True
  526. QTimer.singleShot(5, self.adjustViewableKnobCount)
  527. # -----------------------------------------------------------------
  528. def getFixedHeight(self):
  529. return 32
  530. def getHints(self):
  531. return self.fPluginInfo['hints']
  532. def getPluginId(self):
  533. return self.fPluginId
  534. # -----------------------------------------------------------------
  535. def setPluginId(self, idx):
  536. self.fPluginId = idx
  537. self.fEditDialog.setPluginId(idx)
  538. def setName(self, name):
  539. self.fPluginInfo['name'] = name
  540. self.fEditDialog.setName(name)
  541. if self.label_name is not None:
  542. self.label_name.setText(name)
  543. def setSelected(self, yesNo):
  544. if self.fIsSelected == yesNo:
  545. return
  546. self.fIsSelected = yesNo
  547. self.update()
  548. # -----------------------------------------------------------------
  549. def setActive(self, active, sendCallback=False, sendHost=True):
  550. self.fIsActive = active
  551. if sendCallback:
  552. self.fParameterIconTimer = ICON_STATE_ON
  553. self.activeChanged(active)
  554. if sendHost:
  555. self.host.set_active(self.fPluginId, active)
  556. if active:
  557. self.fEditDialog.clearNotes()
  558. self.midiActivityChanged(False)
  559. if self.label_name is not None:
  560. self.label_name.setEnabled(self.fIsActive)
  561. # called from rack, checks if param is possible first
  562. def setInternalParameter(self, parameterId, value):
  563. if parameterId <= PARAMETER_MAX or parameterId >= PARAMETER_NULL:
  564. return
  565. elif parameterId == PARAMETER_ACTIVE:
  566. return self.setActive(bool(value), True, True)
  567. elif parameterId == PARAMETER_DRYWET:
  568. if (self.fPluginInfo['hints'] & PLUGIN_CAN_DRYWET) == 0: return
  569. self.host.set_drywet(self.fPluginId, value)
  570. elif parameterId == PARAMETER_VOLUME:
  571. if (self.fPluginInfo['hints'] & PLUGIN_CAN_VOLUME) == 0: return
  572. self.host.set_volume(self.fPluginId, value)
  573. elif parameterId == PARAMETER_BALANCE_LEFT:
  574. if (self.fPluginInfo['hints'] & PLUGIN_CAN_BALANCE) == 0: return
  575. self.host.set_balance_left(self.fPluginId, value)
  576. elif parameterId == PARAMETER_BALANCE_RIGHT:
  577. if (self.fPluginInfo['hints'] & PLUGIN_CAN_BALANCE) == 0: return
  578. self.host.set_balance_right(self.fPluginId, value)
  579. elif parameterId == PARAMETER_PANNING:
  580. if (self.fPluginInfo['hints'] & PLUGIN_CAN_PANNING) == 0: return
  581. self.host.set_panning(self.fPluginId, value)
  582. elif parameterId == PARAMETER_CTRL_CHANNEL:
  583. self.host.set_ctrl_channel(self.fPluginId, value)
  584. self.fEditDialog.setParameterValue(parameterId, value)
  585. # -----------------------------------------------------------------
  586. def setParameterValue(self, parameterId, value, sendCallback):
  587. if parameterId == PARAMETER_ACTIVE:
  588. return self.setActive(bool(value), True, False)
  589. self.fEditDialog.setParameterValue(parameterId, value)
  590. if sendCallback:
  591. self.fParameterIconTimer = ICON_STATE_ON
  592. self.editDialogParameterValueChanged(self.fPluginId, parameterId, value)
  593. def setParameterDefault(self, parameterId, value):
  594. self.fEditDialog.setParameterDefault(parameterId, value)
  595. def setParameterMappedControlIndex(self, parameterId, control):
  596. self.fEditDialog.setParameterMappedControlIndex(parameterId, control)
  597. def setParameterMappedRange(self, parameterId, minimum, maximum):
  598. self.fEditDialog.setParameterMappedRange(parameterId, minimum, maximum)
  599. def setParameterMidiChannel(self, parameterId, channel):
  600. self.fEditDialog.setParameterMidiChannel(parameterId, channel)
  601. # -----------------------------------------------------------------
  602. def setProgram(self, index, sendCallback):
  603. self.fEditDialog.setProgram(index)
  604. if sendCallback:
  605. self.fParameterIconTimer = ICON_STATE_ON
  606. self.editDialogProgramChanged(self.fPluginId, index)
  607. self.updateParameterValues()
  608. def setMidiProgram(self, index, sendCallback):
  609. self.fEditDialog.setMidiProgram(index)
  610. if sendCallback:
  611. self.fParameterIconTimer = ICON_STATE_ON
  612. self.editDialogMidiProgramChanged(self.fPluginId, index)
  613. self.updateParameterValues()
  614. # -----------------------------------------------------------------
  615. def setOption(self, option, yesNo):
  616. self.fEditDialog.setOption(option, yesNo)
  617. # -----------------------------------------------------------------
  618. def showCustomUI(self):
  619. self.host.show_custom_ui(self.fPluginId, True)
  620. if self.b_gui is not None:
  621. self.b_gui.setChecked(True)
  622. def hideCustomUI(self):
  623. self.host.show_custom_ui(self.fPluginId, False)
  624. if self.b_gui is not None:
  625. self.b_gui.setChecked(False)
  626. def showEditDialog(self):
  627. self.fEditDialog.show()
  628. self.fEditDialog.activateWindow()
  629. if self.b_edit is not None:
  630. self.b_edit.setChecked(True)
  631. def showRenameDialog(self):
  632. oldName = self.fPluginInfo['name']
  633. newNameTry = QInputDialog.getText(self, self.tr("Rename Plugin"), self.tr("New plugin name:"), QLineEdit.Normal, oldName)
  634. if not (newNameTry[1] and newNameTry[0] and oldName != newNameTry[0]):
  635. return
  636. newName = newNameTry[0]
  637. if not self.host.rename_plugin(self.fPluginId, newName):
  638. CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"),
  639. self.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok)
  640. return
  641. def showReplaceDialog(self):
  642. data = gCarla.gui.showAddPluginDialog()
  643. if data is None:
  644. return
  645. btype, ptype, filename, label, uniqueId, extraPtr = data
  646. if not self.host.replace_plugin(self.fPluginId):
  647. CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to replace plugin"), self.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok)
  648. return
  649. ok = self.host.add_plugin(btype, ptype, filename, None, label, uniqueId, extraPtr, PLUGIN_OPTIONS_NULL)
  650. self.host.replace_plugin(self.host.get_max_plugin_number())
  651. if not ok:
  652. CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to load plugin"), self.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok)
  653. # -----------------------------------------------------------------
  654. def activeChanged(self, onOff):
  655. self.fIsActive = onOff
  656. if self.b_enable is None:
  657. return
  658. self.b_enable.blockSignals(True)
  659. self.b_enable.setChecked(onOff)
  660. self.b_enable.blockSignals(False)
  661. def customUiStateChanged(self, state):
  662. if self.b_gui is None:
  663. return
  664. self.b_gui.blockSignals(True)
  665. if state == 0:
  666. self.b_gui.setChecked(False)
  667. self.b_gui.setEnabled(True)
  668. elif state == 1:
  669. self.b_gui.setChecked(True)
  670. self.b_gui.setEnabled(True)
  671. elif state == -1:
  672. self.b_gui.setChecked(False)
  673. self.b_gui.setEnabled(False)
  674. self.b_gui.blockSignals(False)
  675. def parameterActivityChanged(self, onOff):
  676. if self.led_control is None:
  677. return
  678. self.led_control.setChecked(onOff)
  679. def midiActivityChanged(self, onOff):
  680. if self.led_midi is None:
  681. return
  682. self.led_midi.setChecked(onOff)
  683. def optionChanged(self, option, yesNo):
  684. pass
  685. # -----------------------------------------------------------------
  686. # PluginEdit callbacks
  687. def editDialogVisibilityChanged(self, pluginId, visible):
  688. if self.b_edit is None:
  689. return
  690. self.b_edit.blockSignals(True)
  691. self.b_edit.setChecked(visible)
  692. self.b_edit.blockSignals(False)
  693. def editDialogPluginHintsChanged(self, pluginId, hints):
  694. self.fPluginInfo['hints'] = hints
  695. for paramIndex, paramWidget in self.fParameterList:
  696. if paramIndex == PARAMETER_DRYWET:
  697. paramWidget.setVisible(hints & PLUGIN_CAN_DRYWET)
  698. elif paramIndex == PARAMETER_VOLUME:
  699. paramWidget.setVisible(hints & PLUGIN_CAN_VOLUME)
  700. if self.b_gui is not None:
  701. self.b_gui.setEnabled(bool(hints & PLUGIN_HAS_CUSTOM_UI))
  702. def editDialogParameterValueChanged(self, pluginId, parameterId, value):
  703. for paramIndex, paramWidget in self.fParameterList:
  704. if paramIndex != parameterId:
  705. continue
  706. paramWidget.blockSignals(True)
  707. paramWidget.setValue(value)
  708. paramWidget.blockSignals(False)
  709. break
  710. def editDialogProgramChanged(self, pluginId, index):
  711. if self.cb_presets is None:
  712. return
  713. self.cb_presets.blockSignals(True)
  714. self.cb_presets.setCurrentIndex(index)
  715. self.cb_presets.blockSignals(False)
  716. # FIXME
  717. self.updateParameterValues()
  718. def editDialogMidiProgramChanged(self, pluginId, index):
  719. if self.cb_presets is None:
  720. return
  721. self.cb_presets.blockSignals(True)
  722. self.cb_presets.setCurrentIndex(index)
  723. self.cb_presets.blockSignals(False)
  724. # FIXME
  725. self.updateParameterValues()
  726. def editDialogNotePressed(self, pluginId, note):
  727. pass
  728. def editDialogNoteReleased(self, pluginId, note):
  729. pass
  730. def editDialogMidiActivityChanged(self, pluginId, onOff):
  731. self.midiActivityChanged(onOff)
  732. # -----------------------------------------------------------------
  733. def idleFast(self):
  734. # Input peaks
  735. if self.fPeaksInputCount > 0:
  736. if self.fPeaksInputCount > 1:
  737. peak1 = self.host.get_input_peak_value(self.fPluginId, True)
  738. peak2 = self.host.get_input_peak_value(self.fPluginId, False)
  739. ledState = bool(peak1 != 0.0 or peak2 != 0.0)
  740. if self.peak_in is not None:
  741. self.peak_in.displayMeter(1, peak1)
  742. self.peak_in.displayMeter(2, peak2)
  743. else:
  744. peak = self.host.get_input_peak_value(self.fPluginId, True)
  745. ledState = bool(peak != 0.0)
  746. if self.peak_in is not None:
  747. self.peak_in.displayMeter(1, peak)
  748. if self.fLastGreenLedState != ledState and self.led_audio_in is not None:
  749. self.fLastGreenLedState = ledState
  750. self.led_audio_in.setChecked(ledState)
  751. # Output peaks
  752. if self.fPeaksOutputCount > 0:
  753. if self.fPeaksOutputCount > 1:
  754. peak1 = self.host.get_output_peak_value(self.fPluginId, True)
  755. peak2 = self.host.get_output_peak_value(self.fPluginId, False)
  756. ledState = bool(peak1 != 0.0 or peak2 != 0.0)
  757. if self.peak_out is not None:
  758. self.peak_out.displayMeter(1, peak1)
  759. self.peak_out.displayMeter(2, peak2)
  760. else:
  761. peak = self.host.get_output_peak_value(self.fPluginId, True)
  762. ledState = bool(peak != 0.0)
  763. if self.peak_out is not None:
  764. self.peak_out.displayMeter(1, peak)
  765. if self.fLastBlueLedState != ledState and self.led_audio_out is not None:
  766. self.fLastBlueLedState = ledState
  767. self.led_audio_out.setChecked(ledState)
  768. def idleSlow(self):
  769. if self.fParameterIconTimer == ICON_STATE_ON:
  770. self.parameterActivityChanged(True)
  771. self.fParameterIconTimer = ICON_STATE_WAIT
  772. elif self.fParameterIconTimer == ICON_STATE_WAIT:
  773. self.fParameterIconTimer = ICON_STATE_OFF
  774. elif self.fParameterIconTimer == ICON_STATE_OFF:
  775. self.parameterActivityChanged(False)
  776. self.fParameterIconTimer = ICON_STATE_NULL
  777. self.fEditDialog.idleSlow()
  778. # -----------------------------------------------------------------
  779. def drawOutline(self, painter):
  780. painter.save()
  781. painter.setBrush(Qt.transparent)
  782. w = float(self.width())
  783. h = float(self.height())
  784. painter.setPen(self.shadow_pen)
  785. painter.drawLine(QLineF(0.5, h-1, w-1, h-1))
  786. if self.fIsSelected:
  787. painter.setCompositionMode(QPainter.CompositionMode_Plus)
  788. painter.setPen(self.sel_pen)
  789. painter.drawRect(QRectF(0.5, 0.5, w-1, h-1))
  790. sidelines = [QLineF(1, 1, 1, h-1), QLineF(w-1, 1, w-1, h-1)]
  791. painter.setPen(self.sel_side_pen)
  792. painter.drawLines(sidelines)
  793. painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
  794. painter.restore()
  795. def updateParameterValues(self):
  796. for paramIndex, paramWidget in self.fParameterList:
  797. if paramIndex < 0:
  798. continue
  799. paramWidget.blockSignals(True)
  800. paramWidget.setValue(self.host.get_current_parameter_value(self.fPluginId, paramIndex))
  801. paramWidget.blockSignals(False)
  802. # -----------------------------------------------------------------
  803. @pyqtSlot(bool)
  804. def slot_enableClicked(self, yesNo):
  805. self.setActive(yesNo, False, True)
  806. @pyqtSlot()
  807. def slot_showCustomMenu(self):
  808. menu = QMenu(self)
  809. # -------------------------------------------------------------
  810. # Expand/Minimize and Tweaks
  811. actCompact = menu.addAction(self.tr("Expand") if isinstance(self, PluginSlot_Compact) else self.tr("Minimize"))
  812. actColor = menu.addAction(self.tr("Change Color..."))
  813. actSkin = menu.addAction(self.tr("Change Skin..."))
  814. menu.addSeparator()
  815. # -------------------------------------------------------------
  816. # Find in patchbay, if possible
  817. if self.host.processMode in (ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS,
  818. ENGINE_PROCESS_MODE_PATCHBAY):
  819. actFindInPatchbay = menu.addAction(self.tr("Find plugin in patchbay"))
  820. menu.addSeparator()
  821. else:
  822. actFindInPatchbay = None
  823. # -------------------------------------------------------------
  824. # Move up and down
  825. actMoveUp = menu.addAction(self.tr("Move Up"))
  826. actMoveDown = menu.addAction(self.tr("Move Down"))
  827. if self.fPluginId == 0:
  828. actMoveUp.setEnabled(False)
  829. if self.fPluginId >= self.fParent.getPluginCount():
  830. actMoveDown.setEnabled(False)
  831. # -------------------------------------------------------------
  832. # Bypass and Enable/Disable
  833. actBypass = menu.addAction(self.tr("Bypass"))
  834. actEnable = menu.addAction(self.tr("Disable") if self.fIsActive else self.tr("Enable"))
  835. menu.addSeparator()
  836. if self.fPluginInfo['hints'] & PLUGIN_CAN_DRYWET:
  837. actBypass.setCheckable(True)
  838. actBypass.setChecked(self.host.get_internal_parameter_value(self.fPluginId, PARAMETER_DRYWET) == 0.0)
  839. else:
  840. actBypass.setVisible(False)
  841. # -------------------------------------------------------------
  842. # Reset and Randomize parameters
  843. actReset = menu.addAction(self.tr("Reset parameters"))
  844. actRandom = menu.addAction(self.tr("Randomize parameters"))
  845. menu.addSeparator()
  846. # -------------------------------------------------------------
  847. # Edit and Show Custom UI
  848. actEdit = menu.addAction(self.tr("Edit"))
  849. actGui = menu.addAction(self.tr("Show Custom UI"))
  850. menu.addSeparator()
  851. if self.b_edit is not None:
  852. actEdit.setCheckable(True)
  853. actEdit.setChecked(self.b_edit.isChecked())
  854. else:
  855. actEdit.setVisible(False)
  856. if self.b_gui is not None:
  857. actGui.setCheckable(True)
  858. actGui.setChecked(self.b_gui.isChecked())
  859. actGui.setEnabled(self.b_gui.isEnabled())
  860. else:
  861. actGui.setVisible(False)
  862. # -------------------------------------------------------------
  863. # Other stuff
  864. actClone = menu.addAction(self.tr("Clone"))
  865. actRename = menu.addAction(self.tr("Rename..."))
  866. actReplace = menu.addAction(self.tr("Replace..."))
  867. actRemove = menu.addAction(self.tr("Remove"))
  868. if self.fIdleTimerId != 0:
  869. actRemove.setVisible(False)
  870. if self.host.exportLV2:
  871. menu.addSeparator()
  872. actExportLV2 = menu.addAction(self.tr("Export LV2..."))
  873. else:
  874. actExportLV2 = None
  875. # -------------------------------------------------------------
  876. # exec
  877. actSel = menu.exec_(QCursor.pos())
  878. if not actSel:
  879. return
  880. # -------------------------------------------------------------
  881. # Expand/Minimize
  882. elif actSel == actCompact:
  883. # FIXME
  884. gCarla.gui.compactPlugin(self.fPluginId)
  885. # -------------------------------------------------------------
  886. # Tweaks
  887. elif actSel == actColor:
  888. initial = QColor(self.fSkinColor[0], self.fSkinColor[1], self.fSkinColor[2])
  889. color = QColorDialog.getColor(initial, self, self.tr("Change Color"), QColorDialog.DontUseNativeDialog)
  890. if not color.isValid():
  891. return
  892. color = color.getRgb()[0:3]
  893. colorStr = "%i;%i;%i" % color
  894. gCarla.gui.changePluginColor(self.fPluginId, color, colorStr)
  895. elif actSel == actSkin:
  896. skinList = [
  897. "default",
  898. "3bandeq",
  899. "rncbc",
  900. "calf_black",
  901. "calf_blue",
  902. "classic",
  903. "openav-old",
  904. "openav",
  905. "zynfx",
  906. "presets",
  907. "mpresets",
  908. ]
  909. try:
  910. index = skinList.index(self.fSkinStyle)
  911. except:
  912. index = 0
  913. skin = QInputDialog.getItem(self, self.tr("Change Skin"),
  914. self.tr("Change Skin to:"),
  915. skinList, index, False)
  916. if not all(skin):
  917. return
  918. gCarla.gui.changePluginSkin(self.fPluginId, skin[0])
  919. # -------------------------------------------------------------
  920. # Find in patchbay
  921. elif actSel == actFindInPatchbay:
  922. gCarla.gui.findPluginInPatchbay(self.fPluginId)
  923. # -------------------------------------------------------------
  924. # Move up and down
  925. elif actSel == actMoveUp:
  926. gCarla.gui.switchPlugins(self.fPluginId, self.fPluginId-1)
  927. elif actSel == actMoveDown:
  928. gCarla.gui.switchPlugins(self.fPluginId, self.fPluginId+1)
  929. # -------------------------------------------------------------
  930. # Bypass and Enable/Disable
  931. elif actSel == actBypass:
  932. value = 0.0 if actBypass.isChecked() else 1.0
  933. self.host.set_drywet(self.fPluginId, value)
  934. self.setParameterValue(PARAMETER_DRYWET, value, True)
  935. elif actSel == actEnable:
  936. self.setActive(not self.fIsActive, True, True)
  937. # -------------------------------------------------------------
  938. # Reset and Randomize parameters
  939. elif actSel == actReset:
  940. self.host.reset_parameters(self.fPluginId)
  941. elif actSel == actRandom:
  942. self.host.randomize_parameters(self.fPluginId)
  943. # -------------------------------------------------------------
  944. # Edit and Show Custom UI
  945. elif actSel == actEdit:
  946. self.b_edit.click()
  947. elif actSel == actGui:
  948. self.b_gui.click()
  949. # -------------------------------------------------------------
  950. # Clone
  951. elif actSel == actClone:
  952. if not self.host.clone_plugin(self.fPluginId):
  953. CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"),
  954. self.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok)
  955. # -------------------------------------------------------------
  956. # Rename
  957. elif actSel == actRename:
  958. self.showRenameDialog()
  959. # -------------------------------------------------------------
  960. # Replace
  961. elif actSel == actReplace:
  962. self.showReplaceDialog()
  963. # -------------------------------------------------------------
  964. # Remove
  965. elif actSel == actRemove:
  966. if not self.host.remove_plugin(self.fPluginId):
  967. CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"),
  968. self.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok)
  969. # -------------------------------------------------------------
  970. # Export LV2
  971. elif actSel == actExportLV2:
  972. filepath = QInputDialog.getItem(self, self.tr("Export LV2 Plugin"),
  973. self.tr("Select LV2 Path where plugin will be exported to:"),
  974. CARLA_DEFAULT_LV2_PATH, editable=False)
  975. if not all(filepath):
  976. return
  977. plugname = self.fPluginInfo['name']
  978. filepath = os.path.join(filepath[0], plugname.replace(" ","_"))
  979. if not filepath.endswith(".lv2"):
  980. filepath += ".lv2"
  981. if os.path.exists(filepath):
  982. if QMessageBox.question(self, self.tr("Export to LV2"),
  983. self.tr("Plugin bundle already exists, overwrite?")) == QMessageBox.Ok:
  984. return
  985. if not self.host.export_plugin_lv2(self.fPluginId, filepath):
  986. return CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"),
  987. self.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok)
  988. QMessageBox.information(self, self.tr("Plugin exported"),
  989. self.tr("Plugin exported successfully, saved in folder:\n%s" % filepath))
  990. # -------------------------------------------------------------
  991. @pyqtSlot()
  992. def slot_knobCustomMenu(self):
  993. sender = self.sender()
  994. index = sender.fIndex
  995. minimum = sender.fMinimum
  996. maximum = sender.fMaximum
  997. current = sender.fRealValue
  998. label = sender.fLabel
  999. if index in (PARAMETER_NULL, PARAMETER_CTRL_CHANNEL) or index <= PARAMETER_MAX:
  1000. return
  1001. elif index in (PARAMETER_DRYWET, PARAMETER_VOLUME):
  1002. default = 1.0
  1003. elif index == PARAMETER_BALANCE_LEFT:
  1004. default = -1.0
  1005. elif index == PARAMETER_BALANCE_RIGHT:
  1006. default = 1.0
  1007. elif index == PARAMETER_PANNING:
  1008. default = 0.0
  1009. else:
  1010. default = self.host.get_default_parameter_value(self.fPluginId, index)
  1011. if index < PARAMETER_NULL:
  1012. # show in integer percentage
  1013. textReset = self.tr("Reset (%i%%)" % round(default*100.0))
  1014. textMinim = self.tr("Set to Minimum (%i%%)" % round(minimum*100.0))
  1015. textMaxim = self.tr("Set to Maximum (%i%%)" % round(maximum*100.0))
  1016. else:
  1017. # show in full float value
  1018. textReset = self.tr("Reset (%f)" % default)
  1019. textMinim = self.tr("Set to Minimum (%f)" % minimum)
  1020. textMaxim = self.tr("Set to Maximum (%f)" % maximum)
  1021. menu = QMenu(self)
  1022. actReset = menu.addAction(textReset)
  1023. menu.addSeparator()
  1024. actMinimum = menu.addAction(textMinim)
  1025. actCenter = menu.addAction(self.tr("Set to Center"))
  1026. actMaximum = menu.addAction(textMaxim)
  1027. menu.addSeparator()
  1028. actSet = menu.addAction(self.tr("Set value..."))
  1029. if index > PARAMETER_NULL or index not in (PARAMETER_BALANCE_LEFT, PARAMETER_BALANCE_RIGHT, PARAMETER_PANNING):
  1030. menu.removeAction(actCenter)
  1031. actSelected = menu.exec_(QCursor.pos())
  1032. if actSelected == actSet:
  1033. if index < PARAMETER_NULL:
  1034. value, ok = QInputDialog.getInt(self, self.tr("Set value"), label, round(current*100), round(minimum*100), round(maximum*100), 1)
  1035. if not ok:
  1036. return
  1037. value = float(value)/100.0
  1038. else:
  1039. paramInfo = self.host.get_parameter_info(self.fPluginId, index)
  1040. paramRanges = self.host.get_parameter_ranges(self.fPluginId, index)
  1041. scalePoints = []
  1042. for i in range(paramInfo['scalePointCount']):
  1043. scalePoints.append(self.host.get_parameter_scalepoint_info(self.fPluginId, index, i))
  1044. prefix = ""
  1045. suffix = paramInfo['unit'].strip()
  1046. if suffix == "(coef)":
  1047. prefix = "* "
  1048. suffix = ""
  1049. else:
  1050. suffix = " " + suffix
  1051. dialog = CustomInputDialog(self, label, current, minimum, maximum,
  1052. paramRanges['step'], paramRanges['stepSmall'], scalePoints, prefix, suffix)
  1053. if not dialog.exec_():
  1054. return
  1055. value = dialog.returnValue()
  1056. elif actSelected == actMinimum:
  1057. value = minimum
  1058. elif actSelected == actMaximum:
  1059. value = maximum
  1060. elif actSelected == actReset:
  1061. value = default
  1062. elif actSelected == actCenter:
  1063. value = 0.0
  1064. else:
  1065. return
  1066. sender.setValue(value, True)
  1067. # -----------------------------------------------------------------
  1068. @pyqtSlot(bool)
  1069. def slot_showCustomUi(self, show):
  1070. self.host.show_custom_ui(self.fPluginId, show)
  1071. @pyqtSlot(bool)
  1072. def slot_showEditDialog(self, show):
  1073. self.fEditDialog.setVisible(show)
  1074. @pyqtSlot()
  1075. def slot_removePlugin(self):
  1076. if not self.host.remove_plugin(self.fPluginId):
  1077. CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"),
  1078. self.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok)
  1079. # -----------------------------------------------------------------
  1080. @pyqtSlot(bool)
  1081. def slot_parameterDragStateChanged(self, touch):
  1082. index = self.sender().getIndex()
  1083. if index >= 0:
  1084. self.host.set_parameter_touch(self.fPluginId, index, touch)
  1085. @pyqtSlot(float)
  1086. def slot_parameterValueChanged(self, value):
  1087. index = self.sender().getIndex()
  1088. if index < 0:
  1089. self.setInternalParameter(index, value)
  1090. else:
  1091. self.host.set_parameter_value(self.fPluginId, index, value)
  1092. self.setParameterValue(index, value, False)
  1093. @pyqtSlot(int)
  1094. def slot_programChanged(self, index):
  1095. self.host.set_program(self.fPluginId, index)
  1096. self.setProgram(index, False)
  1097. @pyqtSlot(int)
  1098. def slot_midiProgramChanged(self, index):
  1099. self.host.set_midi_program(self.fPluginId, index)
  1100. self.setMidiProgram(index, False)
  1101. # -----------------------------------------------------------------
  1102. def adjustViewableKnobCount(self):
  1103. if self.w_knobs_left is None or self.spacer_knobs is None:
  1104. return
  1105. curWidth = 2
  1106. maxWidth = self.w_knobs_left.width() + self.spacer_knobs.geometry().width() + 2
  1107. plen = len(self.fParameterList)
  1108. for i in range(plen):
  1109. index, widget = self.fParameterList[i]
  1110. if index < 0:
  1111. break
  1112. curWidth += widget.width() + 4
  1113. if curWidth + widget.width() * 2 + 8 < maxWidth:
  1114. #if not widget.isVisible():
  1115. widget.show()
  1116. continue
  1117. for i2 in range(i, plen):
  1118. index2, widget2 = self.fParameterList[i2]
  1119. if index2 < 0:
  1120. break
  1121. #if widget2.isVisible():
  1122. widget2.hide()
  1123. break
  1124. self.fAdjustViewableKnobCountScheduled = False
  1125. def testTimer(self):
  1126. self.fIdleTimerId = self.startTimer(25)
  1127. # -----------------------------------------------------------------
  1128. def mouseDoubleClickEvent(self, event):
  1129. QFrame.mouseDoubleClickEvent(self, event)
  1130. # FIXME
  1131. gCarla.gui.compactPlugin(self.fPluginId)
  1132. def closeEvent(self, event):
  1133. if self.fIdleTimerId != 0:
  1134. self.killTimer(self.fIdleTimerId)
  1135. self.fIdleTimerId = 0
  1136. self.host.engine_close()
  1137. QFrame.closeEvent(self, event)
  1138. def resizeEvent(self, event):
  1139. if not self.fAdjustViewableKnobCountScheduled:
  1140. self.fAdjustViewableKnobCountScheduled = True
  1141. QTimer.singleShot(100, self.adjustViewableKnobCount)
  1142. QFrame.resizeEvent(self, event)
  1143. def timerEvent(self, event):
  1144. if event.timerId() == self.fIdleTimerId:
  1145. self.host.engine_idle()
  1146. self.idleFast()
  1147. self.idleSlow()
  1148. QFrame.timerEvent(self, event)
  1149. def paintEvent(self, event):
  1150. painter = QPainter(self)
  1151. # Colorization
  1152. if self.fSkinColor != (0,0,0):
  1153. painter.setCompositionMode(QPainter.CompositionMode_Multiply)
  1154. r,g,b = self.fSkinColor
  1155. painter.setBrush(QColor(r,g,b))
  1156. painter.setPen(Qt.NoPen)
  1157. painter.drawRect(QRectF(0,0,self.width(),self.height()))
  1158. painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
  1159. self.drawOutline(painter)
  1160. QFrame.paintEvent(self, event)
  1161. # ------------------------------------------------------------------------------------------------------------
  1162. class PluginSlot_Calf(AbstractPluginSlot):
  1163. def __init__(self, parent, host, pluginId, skinColor, skinStyle):
  1164. AbstractPluginSlot.__init__(self, parent, host, pluginId, skinColor, skinStyle)
  1165. self.ui = ui_carla_plugin_calf.Ui_PluginWidget()
  1166. self.ui.setupUi(self)
  1167. audioCount = self.host.get_audio_port_count_info(self.fPluginId)
  1168. midiCount = self.host.get_midi_port_count_info(self.fPluginId)
  1169. # -------------------------------------------------------------
  1170. # Internal stuff
  1171. self.fButtonFont = self.ui.b_gui.font()
  1172. self.fButtonFont.setBold(False)
  1173. self.fButtonFont.setPixelSize(10)
  1174. self.fButtonColorOn = QColor( 18, 41, 87)
  1175. self.fButtonColorOff = QColor(150, 150, 150)
  1176. # -------------------------------------------------------------
  1177. # Set-up GUI
  1178. self.ui.label_active.setFont(self.fButtonFont)
  1179. self.ui.b_remove.setPixmaps(":/bitmaps/button_calf1.png",
  1180. ":/bitmaps/button_calf1_down.png",
  1181. ":/bitmaps/button_calf1_hover.png")
  1182. self.ui.b_edit.setTopText(self.tr("Edit"), self.fButtonColorOn, self.fButtonFont)
  1183. self.ui.b_remove.setTopText(self.tr("Remove"), self.fButtonColorOn, self.fButtonFont)
  1184. if self.fPluginInfo['hints'] & PLUGIN_HAS_CUSTOM_UI:
  1185. self.ui.b_gui.setTopText(self.tr("GUI"), self.fButtonColorOn, self.fButtonFont)
  1186. else:
  1187. self.ui.b_gui.setTopText(self.tr("GUI"), self.fButtonColorOff, self.fButtonFont)
  1188. if audioCount['ins'] == 0:
  1189. self.ui.label_audio_in.hide()
  1190. if audioCount['outs'] == 0:
  1191. self.ui.label_audio_out.hide()
  1192. if midiCount['ins'] == 0:
  1193. self.ui.label_midi.hide()
  1194. self.ui.led_midi.hide()
  1195. if self.fIdleTimerId != 0:
  1196. self.ui.b_remove.setEnabled(False)
  1197. self.ui.b_remove.setVisible(False)
  1198. # -------------------------------------------------------------
  1199. self.b_enable = self.ui.b_enable
  1200. self.b_gui = self.ui.b_gui
  1201. self.b_edit = self.ui.b_edit
  1202. self.b_remove = self.ui.b_remove
  1203. self.label_name = self.ui.label_name
  1204. self.led_midi = self.ui.led_midi
  1205. self.peak_in = self.ui.peak_in
  1206. self.peak_out = self.ui.peak_out
  1207. self.w_knobs_left = self.ui.w_knobs
  1208. self.spacer_knobs = self.ui.layout_bottom.itemAt(1).spacerItem()
  1209. self.ready()
  1210. self.ui.led_midi.setColor(self.ui.led_midi.CALF)
  1211. # -----------------------------------------------------------------
  1212. def getFixedHeight(self):
  1213. return 94 if max(self.peak_in.channelCount(), self.peak_out.channelCount()) < 2 else 106
  1214. # -----------------------------------------------------------------
  1215. def editDialogPluginHintsChanged(self, pluginId, hints):
  1216. if hints & PLUGIN_HAS_CUSTOM_UI:
  1217. self.ui.b_gui.setTopText(self.tr("GUI"), self.fButtonColorOn, self.fButtonFont)
  1218. else:
  1219. self.ui.b_gui.setTopText(self.tr("GUI"), self.fButtonColorOff, self.fButtonFont)
  1220. AbstractPluginSlot.editDialogPluginHintsChanged(self, pluginId, hints)
  1221. # -----------------------------------------------------------------
  1222. def paintEvent(self, event):
  1223. isBlack = bool(self.fSkinStyle == "calf_black")
  1224. painter = QPainter(self)
  1225. painter.setBrush(Qt.transparent)
  1226. painter.setPen(QPen(QColor(20, 20, 20) if isBlack else QColor(75, 86, 99), 1))
  1227. painter.drawRect(0, 1, self.width()-1, self.height()-3)
  1228. painter.setPen(QPen(QColor(45, 45, 45) if isBlack else QColor(86, 99, 114), 1))
  1229. painter.drawLine(0, 0, self.width(), 0)
  1230. AbstractPluginSlot.paintEvent(self, event)
  1231. # ------------------------------------------------------------------------------------------------------------
  1232. class PluginSlot_Classic(AbstractPluginSlot):
  1233. def __init__(self, parent, host, pluginId):
  1234. AbstractPluginSlot.__init__(self, parent, host, pluginId, (0,0,0), "classic")
  1235. self.ui = ui_carla_plugin_classic.Ui_PluginWidget()
  1236. self.ui.setupUi(self)
  1237. # -------------------------------------------------------------
  1238. # Internal stuff
  1239. self.fColorTop = QColor(60, 60, 60)
  1240. self.fColorBottom = QColor(47, 47, 47)
  1241. self.fColorSeprtr = QColor(70, 70, 70)
  1242. # -------------------------------------------------------------
  1243. self.b_enable = self.ui.b_enable
  1244. self.b_gui = self.ui.b_gui
  1245. self.b_edit = self.ui.b_edit
  1246. self.label_name = self.ui.label_name
  1247. self.led_control = self.ui.led_control
  1248. self.led_midi = self.ui.led_midi
  1249. self.led_audio_in = self.ui.led_audio_in
  1250. self.led_audio_out = self.ui.led_audio_out
  1251. self.peak_in = self.ui.peak_in
  1252. self.peak_out = self.ui.peak_out
  1253. self.ready()
  1254. # -----------------------------------------------------------------
  1255. def getFixedHeight(self):
  1256. return 36
  1257. # -----------------------------------------------------------------
  1258. def paintEvent(self, event):
  1259. painter = QPainter(self)
  1260. painter.save()
  1261. areaX = self.ui.area_right.x()+7
  1262. width = self.width()
  1263. height = self.height()
  1264. painter.setPen(QPen(QColor(17, 17, 17), 1))
  1265. painter.setBrush(QColor(17, 17, 17))
  1266. painter.drawRect(0, 0, width, height)
  1267. painter.setPen(self.fColorSeprtr.lighter(110))
  1268. painter.setBrush(self.fColorBottom)
  1269. painter.setRenderHint(QPainter.Antialiasing, True)
  1270. # name -> leds arc
  1271. path = QPainterPath()
  1272. path.moveTo(areaX-20, height-4)
  1273. path.cubicTo(areaX, height-5, areaX-20, 4.75, areaX, 4.75)
  1274. path.lineTo(areaX, height-5)
  1275. painter.drawPath(path)
  1276. painter.setPen(self.fColorSeprtr)
  1277. painter.setRenderHint(QPainter.Antialiasing, False)
  1278. # separator lines
  1279. painter.drawLine(0, height-5, areaX-20, height-5)
  1280. painter.drawLine(areaX, 4, width, 4)
  1281. painter.setPen(self.fColorBottom)
  1282. painter.setBrush(self.fColorBottom)
  1283. # top, bottom and left lines
  1284. painter.drawLine(0, 0, width, 0)
  1285. painter.drawRect(0, height-4, areaX, 4)
  1286. painter.drawRoundedRect(areaX-20, height-5, areaX, 5, 22, 22)
  1287. painter.drawLine(0, 0, 0, height)
  1288. # fill the rest
  1289. painter.drawRect(areaX-1, 5, width, height)
  1290. # bottom 1px line
  1291. painter.setPen(self.fColorSeprtr)
  1292. painter.drawLine(0, height-1, width, height-1)
  1293. painter.restore()
  1294. AbstractPluginSlot.paintEvent(self, event)
  1295. # ------------------------------------------------------------------------------------------------------------
  1296. class PluginSlot_Compact(AbstractPluginSlot):
  1297. def __init__(self, parent, host, pluginId, skinColor, skinStyle):
  1298. AbstractPluginSlot.__init__(self, parent, host, pluginId, skinColor, skinStyle)
  1299. self.ui = ui_carla_plugin_compact.Ui_PluginWidget()
  1300. self.ui.setupUi(self)
  1301. self.b_enable = self.ui.b_enable
  1302. self.b_gui = self.ui.b_gui
  1303. self.b_edit = self.ui.b_edit
  1304. self.label_name = self.ui.label_name
  1305. self.led_control = self.ui.led_control
  1306. self.led_midi = self.ui.led_midi
  1307. self.led_audio_in = self.ui.led_audio_in
  1308. self.led_audio_out = self.ui.led_audio_out
  1309. self.peak_in = self.ui.peak_in
  1310. self.peak_out = self.ui.peak_out
  1311. self.ready()
  1312. # -----------------------------------------------------------------
  1313. def getFixedHeight(self):
  1314. if self.fSkinStyle == "calf_blue":
  1315. return 36
  1316. return 30
  1317. # ------------------------------------------------------------------------------------------------------------
  1318. class PluginSlot_Default(AbstractPluginSlot):
  1319. def __init__(self, parent, host, pluginId, skinColor, skinStyle):
  1320. AbstractPluginSlot.__init__(self, parent, host, pluginId, skinColor, skinStyle)
  1321. self.ui = ui_carla_plugin_default.Ui_PluginWidget()
  1322. self.ui.setupUi(self)
  1323. # -------------------------------------------------------------
  1324. self.b_enable = self.ui.b_enable
  1325. self.b_gui = self.ui.b_gui
  1326. self.b_edit = self.ui.b_edit
  1327. self.label_name = self.ui.label_name
  1328. self.led_control = self.ui.led_control
  1329. self.led_midi = self.ui.led_midi
  1330. self.led_audio_in = self.ui.led_audio_in
  1331. self.led_audio_out = self.ui.led_audio_out
  1332. self.peak_in = self.ui.peak_in
  1333. self.peak_out = self.ui.peak_out
  1334. self.w_knobs_left = self.ui.w_knobs_left
  1335. self.w_knobs_right = self.ui.w_knobs_right
  1336. self.spacer_knobs = self.ui.layout_bottom.itemAt(1).spacerItem()
  1337. self.ready()
  1338. # -----------------------------------------------------------------
  1339. def getFixedHeight(self):
  1340. return 80
  1341. # -----------------------------------------------------------------
  1342. def paintEvent(self, event):
  1343. painter = QPainter(self)
  1344. painter.setBrush(Qt.transparent)
  1345. painter.setPen(QPen(QColor(42, 42, 42), 1))
  1346. painter.drawRect(0, 1, self.width()-1, self.getFixedHeight()-3)
  1347. painter.setPen(QPen(QColor(60, 60, 60), 1))
  1348. painter.drawLine(0, 0, self.width(), 0)
  1349. AbstractPluginSlot.paintEvent(self, event)
  1350. # ------------------------------------------------------------------------------------------------------------
  1351. class PluginSlot_Presets(AbstractPluginSlot):
  1352. def __init__(self, parent, host, pluginId, skinColor, skinStyle):
  1353. AbstractPluginSlot.__init__(self, parent, host, pluginId, skinColor, skinStyle)
  1354. self.ui = ui_carla_plugin_presets.Ui_PluginWidget()
  1355. self.ui.setupUi(self)
  1356. usingMidiPrograms = bool(skinStyle != "presets")
  1357. # -------------------------------------------------------------
  1358. # Set-up programs
  1359. if usingMidiPrograms:
  1360. programCount = self.host.get_midi_program_count(self.fPluginId)
  1361. else:
  1362. programCount = self.host.get_program_count(self.fPluginId)
  1363. if programCount > 0:
  1364. self.ui.cb_presets.setEnabled(True)
  1365. self.ui.label_presets.setEnabled(True)
  1366. for i in range(programCount):
  1367. if usingMidiPrograms:
  1368. progName = self.host.get_midi_program_data(self.fPluginId, i)['name']
  1369. else:
  1370. progName = self.host.get_program_name(self.fPluginId, i)
  1371. self.ui.cb_presets.addItem(progName)
  1372. if usingMidiPrograms:
  1373. curProg = self.host.get_current_midi_program_index(self.fPluginId)
  1374. else:
  1375. curProg = self.host.get_current_program_index(self.fPluginId)
  1376. self.ui.cb_presets.setCurrentIndex(curProg)
  1377. else:
  1378. self.ui.cb_presets.setEnabled(False)
  1379. self.ui.cb_presets.setVisible(False)
  1380. self.ui.label_presets.setEnabled(False)
  1381. self.ui.label_presets.setVisible(False)
  1382. # -------------------------------------------------------------
  1383. self.b_enable = self.ui.b_enable
  1384. self.b_gui = self.ui.b_gui
  1385. self.b_edit = self.ui.b_edit
  1386. self.cb_presets = self.ui.cb_presets
  1387. self.label_name = self.ui.label_name
  1388. self.label_presets = self.ui.label_presets
  1389. self.led_control = self.ui.led_control
  1390. self.led_midi = self.ui.led_midi
  1391. self.led_audio_in = self.ui.led_audio_in
  1392. self.led_audio_out = self.ui.led_audio_out
  1393. self.peak_in = self.ui.peak_in
  1394. self.peak_out = self.ui.peak_out
  1395. if skinStyle == "zynfx":
  1396. self.setupZynFxParams()
  1397. else:
  1398. self.w_knobs_left = self.ui.w_knobs_left
  1399. self.w_knobs_right = self.ui.w_knobs_right
  1400. self.spacer_knobs = self.ui.layout_bottom.itemAt(1).spacerItem()
  1401. self.ready()
  1402. if usingMidiPrograms:
  1403. self.ui.cb_presets.currentIndexChanged.connect(self.slot_midiProgramChanged)
  1404. else:
  1405. self.ui.cb_presets.currentIndexChanged.connect(self.slot_programChanged)
  1406. # -------------------------------------------------------------
  1407. def setupZynFxParams(self):
  1408. parameterCount = min(self.host.get_parameter_count(self.fPluginId), 8)
  1409. for i in range(parameterCount):
  1410. paramInfo = self.host.get_parameter_info(self.fPluginId, i)
  1411. paramData = self.host.get_parameter_data(self.fPluginId, i)
  1412. paramRanges = self.host.get_parameter_ranges(self.fPluginId, i)
  1413. if paramData['type'] != PARAMETER_INPUT:
  1414. continue
  1415. if paramData['hints'] & PARAMETER_IS_BOOLEAN:
  1416. continue
  1417. if (paramData['hints'] & PARAMETER_IS_ENABLED) == 0:
  1418. continue
  1419. paramName = paramInfo['name']
  1420. if paramName.startswith("unused"):
  1421. continue
  1422. # real zyn fx plugins
  1423. if self.fPluginInfo['label'] == "zynalienwah":
  1424. if i == 0: paramName = "Freq"
  1425. elif i == 1: paramName = "Rnd"
  1426. elif i == 2: paramName = "L type" # combobox
  1427. elif i == 3: paramName = "St.df"
  1428. elif i == 5: paramName = "Fb"
  1429. elif i == 7: paramName = "L/R"
  1430. elif self.fPluginInfo['label'] == "zynchorus":
  1431. if i == 0: paramName = "Freq"
  1432. elif i == 1: paramName = "Rnd"
  1433. elif i == 2: paramName = "L type" # combobox
  1434. elif i == 3: paramName = "St.df"
  1435. elif i == 6: paramName = "Fb"
  1436. elif i == 7: paramName = "L/R"
  1437. elif i == 8: paramName = "Flngr" # button
  1438. elif i == 9: paramName = "Subst" # button
  1439. elif self.fPluginInfo['label'] == "zyndistortion":
  1440. if i == 0: paramName = "LRc."
  1441. elif i == 4: paramName = "Neg." # button
  1442. elif i == 5: paramName = "LPF"
  1443. elif i == 6: paramName = "HPF"
  1444. elif i == 7: paramName = "St." # button
  1445. elif i == 8: paramName = "PF" # button
  1446. elif self.fPluginInfo['label'] == "zyndynamicfilter":
  1447. if i == 0: paramName = "Freq"
  1448. elif i == 1: paramName = "Rnd"
  1449. elif i == 2: paramName = "L type" # combobox
  1450. elif i == 3: paramName = "St.df"
  1451. elif i == 4: paramName = "LfoD"
  1452. elif i == 5: paramName = "A.S."
  1453. elif i == 6: paramName = "A.Inv." # button
  1454. elif i == 7: paramName = "A.M."
  1455. elif self.fPluginInfo['label'] == "zynecho":
  1456. if i == 1: paramName = "LRdl."
  1457. elif i == 2: paramName = "LRc."
  1458. elif i == 3: paramName = "Fb."
  1459. elif i == 4: paramName = "Damp"
  1460. elif self.fPluginInfo['label'] == "zynphaser":
  1461. if i == 0: paramName = "Freq"
  1462. elif i == 1: paramName = "Rnd"
  1463. elif i == 2: paramName = "L type" # combobox
  1464. elif i == 3: paramName = "St.df"
  1465. elif i == 5: paramName = "Fb"
  1466. elif i == 7: paramName = "L/R"
  1467. elif i == 8: paramName = "Subst" # button
  1468. elif i == 9: paramName = "Phase"
  1469. elif i == 11: paramName = "Dist"
  1470. elif self.fPluginInfo['label'] == "zynreverb":
  1471. if i == 2: paramName = "I.delfb"
  1472. elif i == 5: paramName = "LPF"
  1473. elif i == 6: paramName = "HPF"
  1474. elif i == 9: paramName = "R.S."
  1475. elif i == 10: paramName = "I.del"
  1476. else:
  1477. paramName = getParameterShortName(paramName)
  1478. widget = ScalableDial(self, i)
  1479. widget.setLabel(paramName)
  1480. widget.setMinimum(paramRanges['min'])
  1481. widget.setMaximum(paramRanges['max'])
  1482. widget.setImage(3)
  1483. widget.setCustomPaintColor(QColor(83, 173, 10))
  1484. widget.setCustomPaintMode(ScalableDial.CUSTOM_PAINT_MODE_COLOR)
  1485. widget.forceWhiteLabelGradientText()
  1486. widget.hide()
  1487. if (paramData['hints'] & PARAMETER_IS_ENABLED) == 0:
  1488. widget.setEnabled(False)
  1489. self.fParameterList.append([i, widget])
  1490. self.ui.w_knobs_left.layout().addWidget(widget)
  1491. if self.fPluginInfo['hints'] & PLUGIN_CAN_DRYWET:
  1492. widget = ScalableDial(self, PARAMETER_DRYWET)
  1493. widget.setLabel("Wet")
  1494. widget.setMinimum(0.0)
  1495. widget.setMaximum(1.0)
  1496. widget.setImage(3)
  1497. widget.setCustomPaintMode(ScalableDial.CUSTOM_PAINT_MODE_CARLA_WET)
  1498. widget.forceWhiteLabelGradientText()
  1499. self.fParameterList.append([PARAMETER_DRYWET, widget])
  1500. self.ui.w_knobs_right.layout().addWidget(widget)
  1501. if self.fPluginInfo['hints'] & PLUGIN_CAN_VOLUME:
  1502. widget = ScalableDial(self, PARAMETER_VOLUME)
  1503. widget.setLabel("Volume")
  1504. widget.setMinimum(0.0)
  1505. widget.setMaximum(1.27)
  1506. widget.setImage(3)
  1507. widget.setCustomPaintMode(ScalableDial.CUSTOM_PAINT_MODE_CARLA_VOL)
  1508. widget.forceWhiteLabelGradientText()
  1509. self.fParameterList.append([PARAMETER_VOLUME, widget])
  1510. self.ui.w_knobs_right.layout().addWidget(widget)
  1511. # -----------------------------------------------------------------
  1512. def getFixedHeight(self):
  1513. return 80
  1514. # -----------------------------------------------------------------
  1515. def paintEvent(self, event):
  1516. painter = QPainter(self)
  1517. painter.setBrush(Qt.transparent)
  1518. painter.setPen(QPen(QColor(50, 50, 50), 1))
  1519. painter.drawRect(0, 1, self.width()-1, self.height()-3)
  1520. painter.setPen(QPen(QColor(64, 64, 64), 1))
  1521. painter.drawLine(0, 0, self.width(), 0)
  1522. AbstractPluginSlot.paintEvent(self, event)
  1523. # ------------------------------------------------------------------------------------------------------------
  1524. def getColorAndSkinStyle(host, pluginId):
  1525. pluginInfo = host.get_plugin_info(pluginId)
  1526. pluginName = host.get_real_plugin_name(pluginId)
  1527. pluginLabel = pluginInfo['label'].lower()
  1528. pluginMaker = pluginInfo['maker']
  1529. uniqueId = pluginInfo['uniqueId']
  1530. if pluginInfo['type'] in (PLUGIN_VST2, PLUGIN_VST3, PLUGIN_AU):
  1531. progCount = host.get_program_count(pluginId)
  1532. else:
  1533. progCount = host.get_midi_program_count(pluginId)
  1534. colorCategory = getColorFromCategory(pluginInfo['category'])
  1535. colorNone = (0,0,0)
  1536. # Samplers
  1537. if pluginInfo['type'] == PLUGIN_SF2:
  1538. return (colorCategory, "sf2")
  1539. if pluginInfo['type'] == PLUGIN_SFZ:
  1540. return (colorCategory, "sfz")
  1541. # Calf
  1542. if pluginName.split(" ", 1)[0].lower() == "calf":
  1543. return (colorNone, "calf_black" if "mono" in pluginLabel else "calf_blue")
  1544. # OpenAV
  1545. if pluginMaker == "OpenAV Productions":
  1546. return (colorNone, "openav-old")
  1547. if pluginMaker == "OpenAV":
  1548. return (colorNone, "openav")
  1549. # ZynFX
  1550. if pluginInfo['type'] == PLUGIN_INTERNAL:
  1551. if pluginLabel.startswith("zyn") and pluginInfo['category'] != PLUGIN_CATEGORY_SYNTH:
  1552. return (colorNone, "zynfx")
  1553. if pluginInfo['type'] == PLUGIN_LADSPA:
  1554. if pluginLabel.startswith("zyn") and pluginMaker.startswith("Josep Andreu"):
  1555. return (colorNone, "zynfx")
  1556. if pluginInfo['type'] == PLUGIN_LV2:
  1557. if pluginLabel.startswith("http://kxstudio.sf.net/carla/plugins/zyn") and pluginName != "ZynAddSubFX":
  1558. return (colorNone, "zynfx")
  1559. # Presets
  1560. if progCount > 1 and (pluginInfo['hints'] & PLUGIN_USES_MULTI_PROGS) == 0:
  1561. if pluginInfo['type'] in (PLUGIN_VST2, PLUGIN_VST3, PLUGIN_AU):
  1562. return (colorCategory, "presets")
  1563. return (colorCategory, "mpresets")
  1564. # DISTRHO Plugins (needs to be last)
  1565. if pluginMaker.startswith("falkTX, ") or pluginMaker == "DISTRHO" or pluginLabel.startswith("http://distrho.sf.net/plugins/"):
  1566. return (colorNone, pluginLabel.replace("http://distrho.sf.net/plugins/",""))
  1567. return (colorCategory, "default")
  1568. def createPluginSlot(parent, host, pluginId, options):
  1569. skinColor, skinStyle = getColorAndSkinStyle(host, pluginId)
  1570. if options['color'] is not None:
  1571. skinColor = options['color']
  1572. if options['skin']:
  1573. skinStyle = options['skin']
  1574. if skinStyle == "classic":
  1575. return PluginSlot_Classic(parent, host, pluginId)
  1576. if "compact" in skinStyle or options['compact']:
  1577. return PluginSlot_Compact(parent, host, pluginId, skinColor, skinStyle)
  1578. if skinStyle.startswith("calf"):
  1579. return PluginSlot_Calf(parent, host, pluginId, skinColor, skinStyle)
  1580. if skinStyle in ("mpresets", "presets", "zynfx"):
  1581. return PluginSlot_Presets(parent, host, pluginId, skinColor, skinStyle)
  1582. return PluginSlot_Default(parent, host, pluginId, skinColor, skinStyle)
  1583. # ------------------------------------------------------------------------------------------------------------
  1584. # Main Testing
  1585. if __name__ == '__main__':
  1586. from carla_app import CarlaApplication
  1587. from carla_host import initHost, loadHostSettings
  1588. import resources_rc
  1589. app = CarlaApplication("Carla-Skins")
  1590. host = initHost("Skins", None, False, False, False)
  1591. loadHostSettings(host)
  1592. host.engine_init("JACK", "Carla-Widgets")
  1593. host.add_plugin(BINARY_NATIVE, PLUGIN_INTERNAL, "", "", "zynreverb", 0, None, PLUGIN_OPTIONS_NULL)
  1594. #host.add_plugin(BINARY_NATIVE, PLUGIN_DSSI, "/usr/lib/dssi/karplong.so", "karplong", "karplong", 0, None, PLUGIN_OPTIONS_NULL)
  1595. #host.add_plugin(BINARY_NATIVE, PLUGIN_LV2, "", "", "http://www.openavproductions.com/sorcer", 0, None, PLUGIN_OPTIONS_NULL)
  1596. #host.add_plugin(BINARY_NATIVE, PLUGIN_LV2, "", "", "http://calf.sourceforge.net/plugins/Compressor", 0, None, PLUGIN_OPTIONS_NULL)
  1597. host.set_active(0, True)
  1598. #gui = createPluginSlot(None, host, 0, True)
  1599. gui = PluginSlot_Compact(None, host, 0, (0, 0, 0), "default")
  1600. gui.testTimer()
  1601. gui.show()
  1602. app.exec_()