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.py 68KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla plugin host
  4. # Copyright (C) 2011-2013 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 GPL.txt file
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. from PyQt4.QtCore import Qt, QPointF, QSize
  20. from PyQt4.QtGui import QApplication, QDialogButtonBox, QMainWindow, QResizeEvent
  21. # ------------------------------------------------------------------------------------------------------------
  22. # Imports (Custom Stuff)
  23. import patchcanvas
  24. import ui_carla
  25. import ui_carla_settings
  26. from carla_backend import * # FIXME, remove later
  27. from carla_shared import *
  28. # ------------------------------------------------------------------------------------------------------------
  29. # Try Import OpenGL
  30. try:
  31. from PyQt4.QtOpenGL import QGLWidget
  32. hasGL = True
  33. except:
  34. hasGL = False
  35. # ------------------------------------------------------------------------------------------------------------
  36. # Static Variables
  37. DEFAULT_CANVAS_WIDTH = 3100
  38. DEFAULT_CANVAS_HEIGHT = 2400
  39. # Tab indexes
  40. TAB_INDEX_MAIN = 0
  41. TAB_INDEX_CANVAS = 1
  42. TAB_INDEX_CARLA_ENGINE = 2
  43. TAB_INDEX_CARLA_PATHS = 3
  44. TAB_INDEX_NONE = 4
  45. # Single and Multiple client mode is only for JACK,
  46. # but we still want to match QComboBox index to defines,
  47. # so add +2 pos padding if driverName != "JACK".
  48. PROCESS_MODE_NON_JACK_PADDING = 2
  49. # Carla defaults
  50. CARLA_DEFAULT_PROCESS_HIGH_PRECISION = False
  51. CARLA_DEFAULT_MAX_PARAMETERS = 200
  52. CARLA_DEFAULT_FORCE_STEREO = False
  53. CARLA_DEFAULT_USE_DSSI_VST_CHUNKS = False
  54. CARLA_DEFAULT_PREFER_PLUGIN_BRIDGES = False
  55. CARLA_DEFAULT_PREFER_UI_BRIDGES = True
  56. CARLA_DEFAULT_OSC_UI_TIMEOUT = 4000
  57. CARLA_DEFAULT_DISABLE_CHECKS = False
  58. # PatchCanvas defines
  59. CANVAS_ANTIALIASING_SMALL = 1
  60. CANVAS_EYECANDY_SMALL = 1
  61. # ------------------------------------------------------------------------------------------------------------
  62. # Settings Dialog
  63. class CarlaSettingsW(QDialog):
  64. def __init__(self, parent):
  65. QDialog.__init__(self, parent)
  66. self.ui = ui_carla_settings.Ui_CarlaSettingsW()
  67. self.ui.setupUi(self)
  68. # TODO
  69. self.ui.lw_page.hideRow(TAB_INDEX_CANVAS)
  70. # -------------------------------------------------------------
  71. # Load settings
  72. self.loadSettings()
  73. # -------------------------------------------------------------
  74. # Set-up GUI
  75. driverCount = Carla.host.get_engine_driver_count()
  76. for i in range(driverCount):
  77. driverName = cString(Carla.host.get_engine_driver_name(i))
  78. self.ui.cb_engine_audio_driver.addItem(driverName)
  79. #if not hasOpenGL:
  80. #self.cb_canvas_use_opengl.setChecked(False)
  81. #self.cb_canvas_use_opengl.setEnabled(False)
  82. # -------------------------------------------------------------
  83. # Set-up connections
  84. self.connect(self, SIGNAL("accepted()"), SLOT("slot_saveSettings()"))
  85. self.connect(self.ui.buttonBox.button(QDialogButtonBox.Reset), SIGNAL("clicked()"), SLOT("slot_resetSettings()"))
  86. self.connect(self.ui.b_main_def_folder_open, SIGNAL("clicked()"), SLOT("slot_getAndSetProjectPath()"))
  87. self.connect(self.ui.cb_engine_audio_driver, SIGNAL("currentIndexChanged(int)"), SLOT("slot_engineAudioDriverChanged()"))
  88. self.connect(self.ui.b_paths_add, SIGNAL("clicked()"), SLOT("slot_addPluginPath()"))
  89. self.connect(self.ui.b_paths_remove, SIGNAL("clicked()"), SLOT("slot_removePluginPath()"))
  90. self.connect(self.ui.b_paths_change, SIGNAL("clicked()"), SLOT("slot_changePluginPath()"))
  91. self.connect(self.ui.tw_paths, SIGNAL("currentChanged(int)"), SLOT("slot_pluginPathTabChanged(int)"))
  92. self.connect(self.ui.lw_ladspa, SIGNAL("currentRowChanged(int)"), SLOT("slot_pluginPathRowChanged(int)"))
  93. self.connect(self.ui.lw_dssi, SIGNAL("currentRowChanged(int)"), SLOT("slot_pluginPathRowChanged(int)"))
  94. self.connect(self.ui.lw_lv2, SIGNAL("currentRowChanged(int)"), SLOT("slot_pluginPathRowChanged(int)"))
  95. self.connect(self.ui.lw_vst, SIGNAL("currentRowChanged(int)"), SLOT("slot_pluginPathRowChanged(int)"))
  96. self.connect(self.ui.lw_sf2, SIGNAL("currentRowChanged(int)"), SLOT("slot_pluginPathRowChanged(int)"))
  97. # -------------------------------------------------------------
  98. # Post-connect setup
  99. self.ui.lw_ladspa.setCurrentRow(0)
  100. self.ui.lw_dssi.setCurrentRow(0)
  101. self.ui.lw_lv2.setCurrentRow(0)
  102. self.ui.lw_vst.setCurrentRow(0)
  103. self.ui.lw_gig.setCurrentRow(0)
  104. self.ui.lw_sf2.setCurrentRow(0)
  105. self.ui.lw_sfz.setCurrentRow(0)
  106. #QTimer.singleShot(0, self, )
  107. #self.slot_pluginPathTabChanged(self.tw_paths.currentIndex())
  108. self.ui.lw_page.setCurrentCell(0, 0)
  109. def loadSettings(self):
  110. settings = QSettings()
  111. # ---------------------------------------
  112. self.ui.le_main_def_folder.setText(settings.value("Main/DefaultProjectFolder", HOME, type=str))
  113. self.ui.sb_gui_refresh.setValue(settings.value("Main/RefreshInterval", 50, type=int))
  114. # ---------------------------------------
  115. self.ui.cb_canvas_hide_groups.setChecked(settings.value("Canvas/AutoHideGroups", False, type=bool))
  116. self.ui.cb_canvas_bezier_lines.setChecked(settings.value("Canvas/UseBezierLines", True, type=bool))
  117. self.ui.cb_canvas_eyecandy.setCheckState(settings.value("Canvas/EyeCandy", CANVAS_EYECANDY_SMALL, type=int))
  118. self.ui.cb_canvas_use_opengl.setChecked(settings.value("Canvas/UseOpenGL", False, type=bool))
  119. self.ui.cb_canvas_render_aa.setCheckState(settings.value("Canvas/Antialiasing", CANVAS_ANTIALIASING_SMALL, type=int))
  120. self.ui.cb_canvas_render_hq_aa.setChecked(settings.value("Canvas/HighQualityAntialiasing", False, type=bool))
  121. #themeName = settings.value("Canvas/Theme", getDefaultThemeName(), type=str)
  122. #for i in range(Theme.THEME_MAX):
  123. #thisThemeName = getThemeName(i)
  124. #self.ui.cb_canvas_theme.addItem(thisThemeName)
  125. #if thisThemeName == themeName:
  126. #self.ui.cb_canvas_theme.setCurrentIndex(i)
  127. # --------------------------------------------
  128. audioDriver = settings.value("Engine/AudioDriver", "JACK", type=str)
  129. for i in range(self.ui.cb_engine_audio_driver.count()):
  130. if self.ui.cb_engine_audio_driver.itemText(i) == audioDriver:
  131. self.ui.cb_engine_audio_driver.setCurrentIndex(i)
  132. break
  133. else:
  134. self.ui.cb_engine_audio_driver.setCurrentIndex(-1)
  135. if audioDriver == "JACK":
  136. processModeIndex = settings.value("Engine/ProcessMode", PROCESS_MODE_MULTIPLE_CLIENTS, type=int)
  137. self.ui.cb_engine_process_mode_jack.setCurrentIndex(processModeIndex)
  138. self.ui.sw_engine_process_mode.setCurrentIndex(0)
  139. else:
  140. processModeIndex = settings.value("Engine/ProcessMode", PROCESS_MODE_CONTINUOUS_RACK, type=int)
  141. processModeIndex -= PROCESS_MODE_NON_JACK_PADDING
  142. self.ui.cb_engine_process_mode_other.setCurrentIndex(processModeIndex)
  143. self.ui.sw_engine_process_mode.setCurrentIndex(1)
  144. self.ui.sb_engine_max_params.setValue(settings.value("Engine/MaxParameters", CARLA_DEFAULT_MAX_PARAMETERS, type=int))
  145. self.ui.ch_engine_prefer_ui_bridges.setChecked(settings.value("Engine/PreferUiBridges", CARLA_DEFAULT_PREFER_UI_BRIDGES, type=bool))
  146. self.ui.sb_engine_oscgui_timeout.setValue(settings.value("Engine/OscUiTimeout", CARLA_DEFAULT_OSC_UI_TIMEOUT, type=int))
  147. self.ui.ch_engine_disable_checks.setChecked(settings.value("Engine/DisableChecks", CARLA_DEFAULT_DISABLE_CHECKS, type=bool))
  148. self.ui.ch_engine_dssi_chunks.setChecked(settings.value("Engine/UseDssiVstChunks", CARLA_DEFAULT_USE_DSSI_VST_CHUNKS, type=bool))
  149. self.ui.ch_engine_prefer_plugin_bridges.setChecked(settings.value("Engine/PreferPluginBridges", CARLA_DEFAULT_PREFER_PLUGIN_BRIDGES, type=bool))
  150. self.ui.ch_engine_force_stereo.setChecked(settings.value("Engine/ForceStereo", CARLA_DEFAULT_FORCE_STEREO, type=bool))
  151. # --------------------------------------------
  152. ladspas = toList(settings.value("Paths/LADSPA", Carla.LADSPA_PATH))
  153. dssis = toList(settings.value("Paths/DSSI", Carla.DSSI_PATH))
  154. lv2s = toList(settings.value("Paths/LV2", Carla.LV2_PATH))
  155. vsts = toList(settings.value("Paths/VST", Carla.VST_PATH))
  156. gigs = toList(settings.value("Paths/GIG", Carla.GIG_PATH))
  157. sf2s = toList(settings.value("Paths/SF2", Carla.SF2_PATH))
  158. sfzs = toList(settings.value("Paths/SFZ", Carla.SFZ_PATH))
  159. ladspas.sort()
  160. dssis.sort()
  161. lv2s.sort()
  162. vsts.sort()
  163. gigs.sort()
  164. sf2s.sort()
  165. sfzs.sort()
  166. for ladspa in ladspas:
  167. self.ui.lw_ladspa.addItem(ladspa)
  168. for dssi in dssis:
  169. self.ui.lw_dssi.addItem(dssi)
  170. for lv2 in lv2s:
  171. self.ui.lw_lv2.addItem(lv2)
  172. for vst in vsts:
  173. self.ui.lw_vst.addItem(vst)
  174. for gig in gigs:
  175. self.ui.lw_gig.addItem(gig)
  176. for sf2 in sf2s:
  177. self.ui.lw_sf2.addItem(sf2)
  178. for sfz in sfzs:
  179. self.ui.lw_sfz.addItem(sfz)
  180. @pyqtSlot()
  181. def slot_saveSettings(self):
  182. settings = QSettings()
  183. # ---------------------------------------
  184. settings.setValue("Main/RefreshInterval", self.ui.sb_gui_refresh.value())
  185. settings.setValue("Main/DefaultProjectFolder", self.ui.le_main_def_folder.text())
  186. # ---------------------------------------
  187. #settings.setValue("Canvas/Theme", self.ui.cb_canvas_theme.currentText())
  188. #settings.setValue("Canvas/AutoHideGroups", self.ui.cb_canvas_hide_groups.isChecked())
  189. #settings.setValue("Canvas/UseBezierLines", self.ui.cb_canvas_bezier_lines.isChecked())
  190. #settings.setValue("Canvas/UseOpenGL", self.ui.cb_canvas_use_opengl.isChecked())
  191. #settings.setValue("Canvas/HighQualityAntialiasing", self.ui.cb_canvas_render_hq_aa.isChecked())
  192. ## 0, 1, 2 match their enum variants
  193. #settings.setValue("Canvas/EyeCandy", self.ui.cb_canvas_eyecandy.checkState())
  194. #settings.setValue("Canvas/Antialiasing", self.ui.cb_canvas_render_aa.checkState())
  195. # --------------------------------------------
  196. audioDriver = self.ui.cb_engine_audio_driver.currentText()
  197. settings.setValue("Engine/AudioDriver", audioDriver)
  198. if audioDriver == "JACK":
  199. settings.setValue("Engine/ProcessMode", self.ui.cb_engine_process_mode_jack.currentIndex())
  200. else:
  201. settings.setValue("Engine/ProcessMode", self.ui.cb_engine_process_mode_other.currentIndex()+PROCESS_MODE_NON_JACK_PADDING)
  202. settings.setValue("Engine/MaxParameters", self.ui.sb_engine_max_params.value())
  203. settings.setValue("Engine/PreferUiBridges", self.ui.ch_engine_prefer_ui_bridges.isChecked())
  204. settings.setValue("Engine/OscUiTimeout", self.ui.sb_engine_oscgui_timeout.value())
  205. settings.setValue("Engine/DisableChecks", self.ui.ch_engine_disable_checks.isChecked())
  206. settings.setValue("Engine/UseDssiVstChunks", self.ui.ch_engine_dssi_chunks.isChecked())
  207. settings.setValue("Engine/PreferPluginBridges", self.ui.ch_engine_prefer_plugin_bridges.isChecked())
  208. settings.setValue("Engine/ForceStereo", self.ui.ch_engine_force_stereo.isChecked())
  209. # --------------------------------------------
  210. # FIXME - find a cleaner way to do this, *.items() ?
  211. ladspas = []
  212. dssis = []
  213. lv2s = []
  214. vsts = []
  215. gigs = []
  216. sf2s = []
  217. sfzs = []
  218. for i in range(self.ui.lw_ladspa.count()):
  219. ladspas.append(self.ui.lw_ladspa.item(i).text())
  220. for i in range(self.ui.lw_dssi.count()):
  221. dssis.append(self.ui.lw_dssi.item(i).text())
  222. for i in range(self.ui.lw_lv2.count()):
  223. lv2s.append(self.ui.lw_lv2.item(i).text())
  224. for i in range(self.ui.lw_vst.count()):
  225. vsts.append(self.ui.lw_vst.item(i).text())
  226. for i in range(self.ui.lw_gig.count()):
  227. gigs.append(self.ui.lw_gig.item(i).text())
  228. for i in range(self.ui.lw_sf2.count()):
  229. sf2s.append(self.ui.lw_sf2.item(i).text())
  230. for i in range(self.ui.lw_sfz.count()):
  231. sfzs.append(self.ui.lw_sfz.item(i).text())
  232. settings.setValue("Paths/LADSPA", ladspas)
  233. settings.setValue("Paths/DSSI", dssis)
  234. settings.setValue("Paths/LV2", lv2s)
  235. settings.setValue("Paths/VST", vsts)
  236. settings.setValue("Paths/GIG", gigs)
  237. settings.setValue("Paths/SF2", sf2s)
  238. settings.setValue("Paths/SFZ", sfzs)
  239. @pyqtSlot()
  240. def slot_resetSettings(self):
  241. if self.ui.lw_page.currentRow() == TAB_INDEX_MAIN:
  242. self.ui.le_main_def_folder.setText(HOME)
  243. self.ui.sb_gui_refresh.setValue(50)
  244. elif self.ui.lw_page.currentRow() == TAB_INDEX_CANVAS:
  245. self.ui.cb_canvas_theme.setCurrentIndex(0)
  246. self.ui.cb_canvas_hide_groups.setChecked(False)
  247. self.ui.cb_canvas_bezier_lines.setChecked(True)
  248. self.ui.cb_canvas_eyecandy.setCheckState(Qt.PartiallyChecked)
  249. self.ui.cb_canvas_use_opengl.setChecked(False)
  250. self.ui.cb_canvas_render_aa.setCheckState(Qt.PartiallyChecked)
  251. self.ui.cb_canvas_render_hq_aa.setChecked(False)
  252. elif self.ui.lw_page.currentRow() == TAB_INDEX_CARLA_ENGINE:
  253. self.ui.cb_engine_audio_driver.setCurrentIndex(0)
  254. self.ui.sb_engine_max_params.setValue(CARLA_DEFAULT_MAX_PARAMETERS)
  255. self.ui.ch_engine_prefer_ui_bridges.setChecked(CARLA_DEFAULT_PREFER_UI_BRIDGES)
  256. self.ui.sb_engine_oscgui_timeout.setValue(CARLA_DEFAULT_OSC_UI_TIMEOUT)
  257. self.ui.ch_engine_disable_checks.setChecked(CARLA_DEFAULT_DISABLE_CHECKS)
  258. self.ui.ch_engine_dssi_chunks.setChecked(CARLA_DEFAULT_USE_DSSI_VST_CHUNKS)
  259. self.ui.ch_engine_prefer_plugin_bridges.setChecked(CARLA_DEFAULT_PREFER_PLUGIN_BRIDGES)
  260. self.ui.ch_engine_force_stereo.setChecked(CARLA_DEFAULT_FORCE_STEREO)
  261. if self.ui.cb_engine_audio_driver.currentText() == "JACK":
  262. self.ui.cb_engine_process_mode_jack.setCurrentIndex(PROCESS_MODE_MULTIPLE_CLIENTS)
  263. self.ui.sw_engine_process_mode.setCurrentIndex(0)
  264. else:
  265. self.ui.cb_engine_process_mode_other.setCurrentIndex(PROCESS_MODE_CONTINUOUS_RACK-PROCESS_MODE_NON_JACK_PADDING)
  266. self.ui.sw_engine_process_mode.setCurrentIndex(1)
  267. elif self.ui.lw_page.currentRow() == TAB_INDEX_CARLA_PATHS:
  268. if self.ui.tw_paths.currentIndex() == 0:
  269. Carla.LADSPA_PATH.sort()
  270. self.ui.lw_ladspa.clear()
  271. for ladspa in Carla.LADSPA_PATH:
  272. self.ui.lw_ladspa.addItem(ladspa)
  273. elif self.ui.tw_paths.currentIndex() == 1:
  274. Carla.DSSI_PATH.sort()
  275. self.ui.lw_dssi.clear()
  276. for dssi in Carla.DSSI_PATH:
  277. self.ui.lw_dssi.addItem(dssi)
  278. elif self.ui.tw_paths.currentIndex() == 2:
  279. Carla.LV2_PATH.sort()
  280. self.ui.lw_lv2.clear()
  281. for lv2 in Carla.LV2_PATH:
  282. self.ui.lw_lv2.addItem(lv2)
  283. elif self.ui.tw_paths.currentIndex() == 3:
  284. Carla.VST_PATH.sort()
  285. self.ui.lw_vst.clear()
  286. for vst in Carla.VST_PATH:
  287. self.ui.lw_vst.addItem(vst)
  288. elif self.ui.tw_paths.currentIndex() == 4:
  289. Carla.GIG_PATH.sort()
  290. self.ui.lw_gig.clear()
  291. for gig in Carla.GIG_PATH:
  292. self.ui.lw_gig.addItem(gig)
  293. elif self.ui.tw_paths.currentIndex() == 5:
  294. Carla.SF2_PATH.sort()
  295. self.ui.lw_sf2.clear()
  296. for sf2 in Carla.SF2_PATH:
  297. self.ui.lw_sf2.addItem(sf2)
  298. elif self.ui.tw_paths.currentIndex() == 6:
  299. Carla.SFZ_PATH.sort()
  300. self.ui.lw_sfz.clear()
  301. for sfz in Carla.SFZ_PATH:
  302. self.ui.lw_sfz.addItem(sfz)
  303. @pyqtSlot()
  304. def slot_getAndSetProjectPath(self):
  305. pass #getAndSetPath(self, self.le_main_def_folder.text(), self.le_main_def_folder)
  306. @pyqtSlot()
  307. def slot_engineAudioDriverChanged(self):
  308. if self.ui.cb_engine_audio_driver.currentText() == "JACK":
  309. self.ui.sw_engine_process_mode.setCurrentIndex(0)
  310. else:
  311. self.ui.sw_engine_process_mode.setCurrentIndex(1)
  312. @pyqtSlot()
  313. def slot_addPluginPath(self):
  314. newPath = QFileDialog.getExistingDirectory(self, self.tr("Add Path"), "", QFileDialog.ShowDirsOnly)
  315. if newPath:
  316. if self.ui.tw_paths.currentIndex() == 0:
  317. self.ui.lw_ladspa.addItem(newPath)
  318. elif self.ui.tw_paths.currentIndex() == 1:
  319. self.ui.lw_dssi.addItem(newPath)
  320. elif self.ui.tw_paths.currentIndex() == 2:
  321. self.ui.lw_lv2.addItem(newPath)
  322. elif self.ui.tw_paths.currentIndex() == 3:
  323. self.ui.lw_vst.addItem(newPath)
  324. elif self.ui.tw_paths.currentIndex() == 4:
  325. self.ui.lw_gig.addItem(newPath)
  326. elif self.ui.tw_paths.currentIndex() == 5:
  327. self.ui.lw_sf2.addItem(newPath)
  328. elif self.ui.tw_paths.currentIndex() == 6:
  329. self.ui.lw_sfz.addItem(newPath)
  330. @pyqtSlot()
  331. def slot_removePluginPath(self):
  332. if self.ui.tw_paths.currentIndex() == 0:
  333. self.ui.lw_ladspa.takeItem(self.ui.lw_ladspa.currentRow())
  334. elif self.ui.tw_paths.currentIndex() == 1:
  335. self.ui.lw_dssi.takeItem(self.ui.lw_dssi.currentRow())
  336. elif self.ui.tw_paths.currentIndex() == 2:
  337. self.ui.lw_lv2.takeItem(self.ui.lw_lv2.currentRow())
  338. elif self.ui.tw_paths.currentIndex() == 3:
  339. self.ui.lw_vst.takeItem(self.ui.lw_vst.currentRow())
  340. elif self.ui.tw_paths.currentIndex() == 4:
  341. self.ui.lw_gig.takeItem(self.ui.lw_gig.currentRow())
  342. elif self.ui.tw_paths.currentIndex() == 5:
  343. self.ui.lw_sf2.takeItem(self.ui.lw_sf2.currentRow())
  344. elif self.ui.tw_paths.currentIndex() == 6:
  345. self.ui.lw_sfz.takeItem(self.ui.lw_sfz.currentRow())
  346. @pyqtSlot()
  347. def slot_changePluginPath(self):
  348. if self.ui.tw_paths.currentIndex() == 0:
  349. currentPath = self.ui.lw_ladspa.currentItem().text()
  350. elif self.ui.tw_paths.currentIndex() == 1:
  351. currentPath = self.ui.lw_dssi.currentItem().text()
  352. elif self.ui.tw_paths.currentIndex() == 2:
  353. currentPath = self.ui.lw_lv2.currentItem().text()
  354. elif self.ui.tw_paths.currentIndex() == 3:
  355. currentPath = self.ui.lw_vst.currentItem().text()
  356. elif self.ui.tw_paths.currentIndex() == 4:
  357. currentPath = self.ui.lw_gig.currentItem().text()
  358. elif self.ui.tw_paths.currentIndex() == 5:
  359. currentPath = self.ui.lw_sf2.currentItem().text()
  360. elif self.ui.tw_paths.currentIndex() == 6:
  361. currentPath = self.ui.lw_sfz.currentItem().text()
  362. else:
  363. currentPath = ""
  364. newPath = QFileDialog.getExistingDirectory(self, self.tr("Add Path"), currentPath, QFileDialog.ShowDirsOnly)
  365. if newPath:
  366. if self.ui.tw_paths.currentIndex() == 0:
  367. self.ui.lw_ladspa.currentItem().setText(newPath)
  368. elif self.ui.tw_paths.currentIndex() == 1:
  369. self.ui.lw_dssi.currentItem().setText(newPath)
  370. elif self.ui.tw_paths.currentIndex() == 2:
  371. self.ui.lw_lv2.currentItem().setText(newPath)
  372. elif self.ui.tw_paths.currentIndex() == 3:
  373. self.ui.lw_vst.currentItem().setText(newPath)
  374. elif self.ui.tw_paths.currentIndex() == 4:
  375. self.ui.lw_gig.currentItem().setText(newPath)
  376. elif self.ui.tw_paths.currentIndex() == 5:
  377. self.ui.lw_sf2.currentItem().setText(newPath)
  378. elif self.ui.tw_paths.currentIndex() == 6:
  379. self.ui.lw_sfz.currentItem().setText(newPath)
  380. @pyqtSlot(int)
  381. def slot_pluginPathTabChanged(self, index):
  382. if index == 0:
  383. row = self.ui.lw_ladspa.currentRow()
  384. elif index == 1:
  385. row = self.ui.lw_dssi.currentRow()
  386. elif index == 2:
  387. row = self.ui.lw_lv2.currentRow()
  388. elif index == 3:
  389. row = self.ui.lw_vst.currentRow()
  390. elif index == 4:
  391. row = self.ui.lw_gig.currentRow()
  392. elif index == 5:
  393. row = self.ui.lw_sf2.currentRow()
  394. elif index == 6:
  395. row = self.ui.lw_sfz.currentRow()
  396. else:
  397. row = -1
  398. check = bool(row >= 0)
  399. self.ui.b_paths_remove.setEnabled(check)
  400. self.ui.b_paths_change.setEnabled(check)
  401. @pyqtSlot(int)
  402. def slot_pluginPathRowChanged(self, row):
  403. check = bool(row >= 0)
  404. self.ui.b_paths_remove.setEnabled(check)
  405. self.ui.b_paths_change.setEnabled(check)
  406. def done(self, r):
  407. QDialog.done(self, r)
  408. self.close()
  409. # ------------------------------------------------------------------------------------------------------------
  410. # Main Window
  411. class CarlaMainW(QMainWindow):
  412. def __init__(self, parent=None):
  413. QMainWindow.__init__(self, parent)
  414. self.ui = ui_carla.Ui_CarlaMainW()
  415. self.ui.setupUi(self)
  416. # -------------------------------------------------------------
  417. # Load Settings
  418. self.loadSettings(True)
  419. self.loadRDFs()
  420. self.setStyleSheet("""
  421. QWidget#w_plugins {
  422. background-color: qlineargradient(spread:pad,
  423. x1:0.0, y1:0.0,
  424. x2:0.2, y2:1.0,
  425. stop:0 rgb( 7, 7, 7),
  426. stop:1 rgb(28, 28, 28)
  427. );
  428. }
  429. """)
  430. # -------------------------------------------------------------
  431. # Internal stuff
  432. self.fEngineStarted = False
  433. self.fFirstEngineInit = False
  434. self.fProjectFilename = None
  435. self.fProjectLoading = False
  436. self.fPluginCount = 0
  437. self.fPluginList = []
  438. self.fIdleTimerFast = 0
  439. self.fIdleTimerSlow = 0
  440. #self._nsmAnnounce2str = ""
  441. #self._nsmOpen1str = ""
  442. #self._nsmOpen2str = ""
  443. #self.nsm_server = None
  444. #self.nsm_url = None
  445. # -------------------------------------------------------------
  446. # Set-up GUI stuff
  447. self.ui.act_engine_start.setEnabled(False)
  448. self.ui.act_engine_stop.setEnabled(False)
  449. self.ui.act_plugin_remove_all.setEnabled(False)
  450. # FIXME: Qt4 needs this so it properly create & resize the canvas
  451. self.ui.tabWidget.setCurrentIndex(1)
  452. self.ui.tabWidget.setCurrentIndex(0)
  453. # -------------------------------------------------------------
  454. # Set-up Canvas
  455. self.scene = patchcanvas.PatchScene(self, self.ui.graphicsView)
  456. self.ui.graphicsView.setScene(self.scene)
  457. #self.ui.graphicsView.setRenderHint(QPainter.Antialiasing, bool(self.fSavedSettings["Canvas/Antialiasing"] == patchcanvas.ANTIALIASING_FULL))
  458. #if self.fSavedSettings["Canvas/UseOpenGL"] and hasGL:
  459. #self.ui.graphicsView.setViewport(QGLWidget(self.ui.graphicsView))
  460. #self.ui.graphicsView.setRenderHint(QPainter.HighQualityAntialiasing, self.fSavedSettings["Canvas/HighQualityAntialiasing"])
  461. pOptions = patchcanvas.options_t()
  462. pOptions.theme_name = self.fSavedSettings["Canvas/Theme"]
  463. pOptions.auto_hide_groups = self.fSavedSettings["Canvas/AutoHideGroups"]
  464. pOptions.use_bezier_lines = self.fSavedSettings["Canvas/UseBezierLines"]
  465. pOptions.antialiasing = self.fSavedSettings["Canvas/Antialiasing"]
  466. pOptions.eyecandy = self.fSavedSettings["Canvas/EyeCandy"]
  467. pFeatures = patchcanvas.features_t()
  468. pFeatures.group_info = False
  469. pFeatures.group_rename = False
  470. pFeatures.port_info = False
  471. pFeatures.port_rename = False
  472. pFeatures.handle_group_pos = True
  473. patchcanvas.setOptions(pOptions)
  474. patchcanvas.setFeatures(pFeatures)
  475. patchcanvas.init("Carla", self.scene, canvasCallback, False)
  476. patchcanvas.setCanvasSize(0, 0, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT)
  477. patchcanvas.setInitialPos(DEFAULT_CANVAS_WIDTH / 2, DEFAULT_CANVAS_HEIGHT / 2)
  478. self.ui.graphicsView.setSceneRect(0, 0, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT)
  479. # -------------------------------------------------------------
  480. # Set-up Canvas Preview
  481. self.ui.miniCanvasPreview.setRealParent(self)
  482. self.ui.miniCanvasPreview.setViewTheme(patchcanvas.canvas.theme.canvas_bg, patchcanvas.canvas.theme.rubberband_brush, patchcanvas.canvas.theme.rubberband_pen.color())
  483. self.ui.miniCanvasPreview.init(self.scene, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT)
  484. QTimer.singleShot(100, self, SLOT("slot_miniCanvasInit()"))
  485. #self.m_fakeEdit = PluginEdit(self, -1)
  486. #self.m_curEdit = self.m_fakeEdit
  487. #self.w_edit.layout().addWidget(self.m_curEdit)
  488. #self.w_edit.layout().addStretch()
  489. # -------------------------------------------------------------
  490. # Connect actions to functions
  491. self.connect(self.ui.act_file_new, SIGNAL("triggered()"), SLOT("slot_fileNew()"))
  492. self.connect(self.ui.act_file_open, SIGNAL("triggered()"), SLOT("slot_fileOpen()"))
  493. self.connect(self.ui.act_file_save, SIGNAL("triggered()"), SLOT("slot_fileSave()"))
  494. self.connect(self.ui.act_file_save_as, SIGNAL("triggered()"), SLOT("slot_fileSaveAs()"))
  495. self.connect(self.ui.act_engine_start, SIGNAL("triggered()"), SLOT("slot_engineStart()"))
  496. self.connect(self.ui.act_engine_stop, SIGNAL("triggered()"), SLOT("slot_engineStop()"))
  497. self.connect(self.ui.act_plugin_add, SIGNAL("triggered()"), SLOT("slot_pluginAdd()"))
  498. self.connect(self.ui.act_plugin_remove_all, SIGNAL("triggered()"), SLOT("slot_pluginRemoveAll()"))
  499. self.connect(self.ui.act_settings_configure, SIGNAL("triggered()"), SLOT("slot_configureCarla()"))
  500. self.connect(self.ui.act_help_about, SIGNAL("triggered()"), SLOT("slot_aboutCarla()"))
  501. self.connect(self.ui.act_help_about_qt, SIGNAL("triggered()"), app, SLOT("aboutQt()"))
  502. self.connect(self.ui.ch_transport, SIGNAL("currentIndexChanged(int)"), SLOT("slot_transportModeChanged(int)"))
  503. self.connect(self.ui.b_transport_play, SIGNAL("clicked(bool)"), SLOT("slot_transportPlayPause(bool)"))
  504. self.connect(self.ui.b_transport_stop, SIGNAL("clicked()"), SLOT("slot_transportStop()"))
  505. self.connect(self.ui.miniCanvasPreview, SIGNAL("miniCanvasMoved(double, double)"), SLOT("slot_miniCanvasMoved(double, double)"))
  506. self.connect(self.ui.graphicsView.horizontalScrollBar(), SIGNAL("valueChanged(int)"), SLOT("slot_horizontalScrollBarChanged(int)"))
  507. self.connect(self.ui.graphicsView.verticalScrollBar(), SIGNAL("valueChanged(int)"), SLOT("slot_verticalScrollBarChanged(int)"))
  508. self.connect(self.scene, SIGNAL("sceneGroupMoved(int, int, QPointF)"), SLOT("slot_canvasItemMoved(int, int, QPointF)"))
  509. self.connect(self.scene, SIGNAL("scaleChanged(double)"), SLOT("slot_canvasScaleChanged(double)"))
  510. self.connect(self, SIGNAL("SIGUSR1()"), SLOT("slot_handleSIGUSR1()"))
  511. self.connect(self, SIGNAL("SIGTERM()"), SLOT("slot_handleSIGTERM()"))
  512. self.connect(self, SIGNAL("DebugCallback(int, int, int, double, QString)"), SLOT("slot_handleDebugCallback(int, int, int, double, QString)"))
  513. self.connect(self, SIGNAL("PluginAddedCallback(int)"), SLOT("slot_handlePluginAddedCallback(int)"))
  514. self.connect(self, SIGNAL("PluginRemovedCallback(int)"), SLOT("slot_handlePluginRemovedCallback(int)"))
  515. self.connect(self, SIGNAL("PluginRenamedCallback(int, QString)"), SLOT("slot_handlePluginRenamedCallback(int, QString)"))
  516. self.connect(self, SIGNAL("ParameterValueChangedCallback(int, int, double)"), SLOT("slot_handleParameterValueChangedCallback(int, int, double)"))
  517. self.connect(self, SIGNAL("ParameterDefaultChangedCallback(int, int, double)"), SLOT("slot_handleParameterDefaultChangedCallback(int, int, double)"))
  518. self.connect(self, SIGNAL("ParameterMidiChannelChangedCallback(int, int, int)"), SLOT("slot_handleParameterMidiChannelChangedCallback(int, int, int)"))
  519. self.connect(self, SIGNAL("ParameterMidiCcChangedCallback(int, int, int)"), SLOT("slot_handleParameterMidiCcChangedCallback(int, int, int)"))
  520. self.connect(self, SIGNAL("ProgramChangedCallback(int, int)"), SLOT("slot_handleProgramChangedCallback(int, int)"))
  521. self.connect(self, SIGNAL("MidiProgramChangedCallback(int, int)"), SLOT("slot_handleMidiProgramChangedCallback(int, int)"))
  522. self.connect(self, SIGNAL("NoteOnCallback(int, int, int, int)"), SLOT("slot_handleNoteOnCallback(int, int, int, int)"))
  523. self.connect(self, SIGNAL("NoteOffCallback(int, int, int)"), SLOT("slot_handleNoteOffCallback(int, int, int)"))
  524. self.connect(self, SIGNAL("ShowGuiCallback(int, int)"), SLOT("slot_handleShowGuiCallback(int, int)"))
  525. self.connect(self, SIGNAL("UpdateCallback(int)"), SLOT("slot_handleUpdateCallback(int)"))
  526. self.connect(self, SIGNAL("ReloadInfoCallback(int)"), SLOT("slot_handleReloadInfoCallback(int)"))
  527. self.connect(self, SIGNAL("ReloadParametersCallback(int)"), SLOT("slot_handleReloadParametersCallback(int)"))
  528. self.connect(self, SIGNAL("ReloadProgramsCallback(int)"), SLOT("slot_handleReloadProgramsCallback(int)"))
  529. self.connect(self, SIGNAL("ReloadAllCallback(int)"), SLOT("slot_handleReloadAllCallback(int)"))
  530. self.connect(self, SIGNAL("PatchbayClientAddedCallback(int, QString)"), SLOT("slot_handlePatchbayClientAddedCallback(int, QString)"))
  531. self.connect(self, SIGNAL("PatchbayClientRemovedCallback(int)"), SLOT("slot_handlePatchbayClientRemovedCallback(int)"))
  532. self.connect(self, SIGNAL("PatchbayClientRenamedCallback(int, QString)"), SLOT("slot_handlePatchbayClientRenamedCallback(int, QString)"))
  533. self.connect(self, SIGNAL("PatchbayPortAddedCallback(int, int, int, QString)"), SLOT("slot_handlePatchbayPortAddedCallback(int, int, int, QString)"))
  534. self.connect(self, SIGNAL("PatchbayPortRemovedCallback(int)"), SLOT("slot_handlePatchbayPortRemovedCallback(int)"))
  535. self.connect(self, SIGNAL("PatchbayPortRenamedCallback(int, QString)"), SLOT("slot_handlePatchbayPortRenamedCallback(int, QString)"))
  536. self.connect(self, SIGNAL("PatchbayConnectionAddedCallback(int, int, int)"), SLOT("slot_handlePatchbayConnectionAddedCallback(int, int, int)"))
  537. self.connect(self, SIGNAL("PatchbayConnectionRemovedCallback(int)"), SLOT("slot_handlePatchbayConnectionRemovedCallback(int)"))
  538. #self.connect(self, SIGNAL("NSM_AnnounceCallback()"), SLOT("slot_handleNSM_AnnounceCallback()"))
  539. #self.connect(self, SIGNAL("NSM_Open1Callback()"), SLOT("slot_handleNSM_Open1Callback()"))
  540. #self.connect(self, SIGNAL("NSM_Open2Callback()"), SLOT("slot_handleNSM_Open2Callback()"))
  541. #self.connect(self, SIGNAL("NSM_SaveCallback()"), SLOT("slot_handleNSM_SaveCallback()"))
  542. self.connect(self, SIGNAL("ErrorCallback(QString)"), SLOT("slot_handleErrorCallback(QString)"))
  543. self.connect(self, SIGNAL("QuitCallback()"), SLOT("slot_handleQuitCallback()"))
  544. #NSM_URL = os.getenv("NSM_URL")
  545. #if NSM_URL:
  546. #Carla.host.nsm_announce(NSM_URL, os.getpid())
  547. #else:
  548. QTimer.singleShot(0, self, SLOT("slot_engineStart()"))
  549. @pyqtSlot(float)
  550. def slot_canvasScaleChanged(self, scale):
  551. self.ui.miniCanvasPreview.setViewScale(scale)
  552. @pyqtSlot(int, int, QPointF)
  553. def slot_canvasItemMoved(self, group_id, split_mode, pos):
  554. self.ui.miniCanvasPreview.update()
  555. @pyqtSlot(int)
  556. def slot_horizontalScrollBarChanged(self, value):
  557. maximum = self.ui.graphicsView.horizontalScrollBar().maximum()
  558. if maximum == 0:
  559. xp = 0
  560. else:
  561. xp = float(value) / maximum
  562. self.ui.miniCanvasPreview.setViewPosX(xp)
  563. @pyqtSlot(int)
  564. def slot_verticalScrollBarChanged(self, value):
  565. maximum = self.ui.graphicsView.verticalScrollBar().maximum()
  566. if maximum == 0:
  567. yp = 0
  568. else:
  569. yp = float(value) / maximum
  570. self.ui.miniCanvasPreview.setViewPosY(yp)
  571. @pyqtSlot()
  572. def slot_miniCanvasInit(self):
  573. settings = QSettings()
  574. self.ui.graphicsView.horizontalScrollBar().setValue(settings.value("HorizontalScrollBarValue", DEFAULT_CANVAS_WIDTH / 3, type=int))
  575. self.ui.graphicsView.verticalScrollBar().setValue(settings.value("VerticalScrollBarValue", DEFAULT_CANVAS_HEIGHT * 3 / 8, type=int))
  576. @pyqtSlot(float, float)
  577. def slot_miniCanvasMoved(self, xp, yp):
  578. self.ui.graphicsView.horizontalScrollBar().setValue(xp * DEFAULT_CANVAS_WIDTH)
  579. self.ui.graphicsView.verticalScrollBar().setValue(yp * DEFAULT_CANVAS_HEIGHT)
  580. @pyqtSlot()
  581. def slot_miniCanvasCheckAll(self):
  582. self.slot_miniCanvasCheckSize()
  583. self.slot_horizontalScrollBarChanged(self.ui.graphicsView.horizontalScrollBar().value())
  584. self.slot_verticalScrollBarChanged(self.ui.graphicsView.verticalScrollBar().value())
  585. @pyqtSlot()
  586. def slot_miniCanvasCheckSize(self):
  587. self.ui.miniCanvasPreview.setViewSize(float(self.ui.graphicsView.width()) / DEFAULT_CANVAS_WIDTH, float(self.ui.graphicsView.height()) / DEFAULT_CANVAS_HEIGHT)
  588. def startEngine(self, clientName = "Carla"):
  589. # ---------------------------------------------
  590. # Engine settings
  591. settings = QSettings()
  592. Carla.processMode = settings.value("Engine/ProcessMode", PROCESS_MODE_MULTIPLE_CLIENTS, type=int)
  593. Carla.maxParameters = settings.value("Engine/MaxParameters", MAX_DEFAULT_PARAMETERS, type=int)
  594. transportMode = settings.value("Engine/TransportMode", TRANSPORT_MODE_JACK, type=int)
  595. forceStereo = settings.value("Engine/ForceStereo", False, type=bool)
  596. preferPluginBridges = settings.value("Engine/PreferPluginBridges", False, type=bool)
  597. preferUiBridges = settings.value("Engine/PreferUiBridges", True, type=bool)
  598. useDssiVstChunks = settings.value("Engine/UseDssiVstChunks", False, type=bool)
  599. oscUiTimeout = settings.value("Engine/OscUiTimeout", 40, type=int)
  600. preferredBufferSize = settings.value("Engine/PreferredBufferSize", 512, type=int)
  601. preferredSampleRate = settings.value("Engine/PreferredSampleRate", 44100, type=int)
  602. if Carla.processMode == PROCESS_MODE_CONTINUOUS_RACK:
  603. forceStereo = True
  604. elif Carla.processMode == PROCESS_MODE_MULTIPLE_CLIENTS and os.getenv("LADISH_APP_NAME"):
  605. print("LADISH detected but using multiple clients (not allowed), forcing single client now")
  606. Carla.processMode = PROCESS_MODE_SINGLE_CLIENT
  607. Carla.host.set_engine_option(OPTION_PROCESS_MODE, Carla.processMode, "")
  608. Carla.host.set_engine_option(OPTION_MAX_PARAMETERS, Carla.maxParameters, "")
  609. Carla.host.set_engine_option(OPTION_FORCE_STEREO, forceStereo, "")
  610. Carla.host.set_engine_option(OPTION_PREFER_PLUGIN_BRIDGES, preferPluginBridges, "")
  611. Carla.host.set_engine_option(OPTION_PREFER_UI_BRIDGES, preferUiBridges, "")
  612. Carla.host.set_engine_option(OPTION_USE_DSSI_VST_CHUNKS, useDssiVstChunks, "")
  613. Carla.host.set_engine_option(OPTION_OSC_UI_TIMEOUT, oscUiTimeout, "")
  614. Carla.host.set_engine_option(OPTION_PREFERRED_BUFFER_SIZE, preferredBufferSize, "")
  615. Carla.host.set_engine_option(OPTION_PREFERRED_SAMPLE_RATE, preferredSampleRate, "")
  616. # ---------------------------------------------
  617. # Start
  618. audioDriver = settings.value("Engine/AudioDriver", "JACK", type=str)
  619. if not Carla.host.engine_init(audioDriver, clientName):
  620. if self.fFirstEngineInit:
  621. self.fFirstEngineInit = False
  622. return
  623. audioError = cString(Carla.host.get_last_error())
  624. if audioError:
  625. QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s', possible reasons:\n%s" % (audioDriver, audioError)))
  626. else:
  627. QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s'" % audioDriver))
  628. return
  629. self.fEngineStarted = True
  630. self.fFirstEngineInit = False
  631. self.fPluginCount = 0
  632. self.fPluginList = []
  633. if Carla.processMode == PROCESS_MODE_CONTINUOUS_RACK:
  634. maxCount = MAX_RACK_PLUGINS
  635. elif Carla.processMode == PROCESS_MODE_PATCHBAY:
  636. maxCount = MAX_PATCHBAY_PLUGINS
  637. else:
  638. maxCount = MAX_DEFAULT_PLUGINS
  639. self.ui.ch_transport.blockSignals(True)
  640. self.ui.ch_transport.addItem(self.tr("Internal"))
  641. if audioDriver == "JACK":
  642. self.ui.ch_transport.addItem(self.tr("JACK"))
  643. elif transportMode == TRANSPORT_MODE_JACK:
  644. transportMode = TRANSPORT_MODE_INTERNAL
  645. self.ui.ch_transport.setCurrentIndex(transportMode)
  646. self.ui.ch_transport.blockSignals(False)
  647. for x in range(maxCount):
  648. self.fPluginList.append(None)
  649. Carla.host.set_engine_option(OPTION_TRANSPORT_MODE, transportMode, "")
  650. # Peaks
  651. self.fIdleTimerFast = self.startTimer(self.fSavedSettings["Main/RefreshInterval"])
  652. # LEDs and edit dialog parameters
  653. self.fIdleTimerSlow = self.startTimer(self.fSavedSettings["Main/RefreshInterval"]*2)
  654. def stopEngine(self):
  655. if self.fPluginCount > 0:
  656. ask = QMessageBox.question(self, self.tr("Warning"), self.tr("There are still some plugins loaded, you need to remove them to stop the engine.\n"
  657. "Do you want to do this now?"),
  658. QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
  659. if ask != QMessageBox.Yes:
  660. return
  661. self.removeAllPlugins()
  662. if Carla.host.is_engine_running() and not Carla.host.engine_close():
  663. print(cString(Carla.host.get_last_error()))
  664. self.fEngineStarted = False
  665. self.fPluginCount = 0
  666. self.fPluginList = []
  667. self.killTimer(self.fIdleTimerFast)
  668. self.killTimer(self.fIdleTimerSlow)
  669. settings = QSettings()
  670. settings.setValue("Engine/TransportMode", self.ui.ch_transport.currentIndex())
  671. self.ui.ch_transport.blockSignals(True)
  672. self.ui.ch_transport.clear()
  673. self.ui.ch_transport.blockSignals(False)
  674. patchcanvas.clear()
  675. def loadProject(self, filename):
  676. self.fProjectFilename = filename
  677. self.setWindowTitle("Carla - %s" % os.path.basename(filename))
  678. self.fProjectLoading = True
  679. Carla.host.load_project(filename)
  680. self.fProjectLoading = False
  681. def loadProjectLater(self, filename):
  682. self.fProjectFilename = filename
  683. self.setWindowTitle("Carla - %s" % os.path.basename(filename))
  684. QTimer.singleShot(0, self, SLOT("slot_loadProjectLater()"))
  685. def saveProject(self, filename):
  686. self.fProjectFilename = filename
  687. self.setWindowTitle("Carla - %s" % os.path.basename(filename))
  688. Carla.host.save_project(filename)
  689. def addPlugin(self, btype, ptype, filename, name, label, extraStuff):
  690. if not self.fEngineStarted:
  691. QMessageBox.warning(self, self.tr("Warning"), self.tr("Cannot add new plugins while engine is stopped"))
  692. return False
  693. if not Carla.host.add_plugin(btype, ptype, filename, name, label, extraStuff):
  694. CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to load plugin"), cString(Carla.host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)
  695. return False
  696. return True
  697. def removeAllPlugins(self):
  698. while (self.ui.w_plugins.layout().takeAt(0)):
  699. pass
  700. self.ui.act_plugin_remove_all.setEnabled(False)
  701. for i in range(self.fPluginCount):
  702. pwidget = self.fPluginList[i]
  703. if pwidget is None:
  704. break
  705. self.fPluginList[i] = None
  706. pwidget.ui.edit_dialog.close()
  707. pwidget.close()
  708. pwidget.deleteLater()
  709. del pwidget
  710. self.fPluginCount = 0
  711. Carla.host.remove_all_plugins()
  712. @pyqtSlot()
  713. def slot_fileNew(self):
  714. self.removeAllPlugins()
  715. self.fProjectFilename = None
  716. self.fProjectLoading = False
  717. self.setWindowTitle("Carla")
  718. @pyqtSlot()
  719. def slot_fileOpen(self):
  720. fileFilter = self.tr("Carla Project File (*.carxp)")
  721. filenameTry = QFileDialog.getOpenFileName(self, self.tr("Open Carla Project File"), self.fSavedSettings["Main/DefaultProjectFolder"], filter=fileFilter)
  722. if filenameTry:
  723. # FIXME - show dialog to user
  724. self.removeAllPlugins()
  725. self.loadProject(filenameTry)
  726. @pyqtSlot()
  727. def slot_fileSave(self, saveAs=False):
  728. if self.fProjectFilename and not saveAs:
  729. return self.saveProject(self.fProjectFilename)
  730. fileFilter = self.tr("Carla Project File (*.carxp)")
  731. filenameTry = QFileDialog.getSaveFileName(self, self.tr("Save Carla Project File"), self.fSavedSettings["Main/DefaultProjectFolder"], filter=fileFilter)
  732. if filenameTry:
  733. if not filenameTry.endswith(".carxp"):
  734. filenameTry += ".carxp"
  735. self.saveProject(filenameTry)
  736. @pyqtSlot()
  737. def slot_fileSaveAs(self):
  738. self.slot_fileSave(True)
  739. @pyqtSlot()
  740. def slot_loadProjectLater(self):
  741. self.fProjectLoading = True
  742. Carla.host.load_project(self.fProjectFilename)
  743. self.fProjectLoading = False
  744. @pyqtSlot()
  745. def slot_engineStart(self):
  746. self.startEngine()
  747. check = Carla.host.is_engine_running()
  748. self.ui.act_file_open.setEnabled(check)
  749. self.ui.act_engine_start.setEnabled(not check)
  750. self.ui.act_engine_stop.setEnabled(check)
  751. self.ui.act_engine_configure.setEnabled(not check)
  752. self.ui.frame_transport.setEnabled(check)
  753. @pyqtSlot()
  754. def slot_engineStop(self):
  755. self.stopEngine()
  756. check = Carla.host.is_engine_running()
  757. self.ui.act_file_open.setEnabled(check)
  758. self.ui.act_engine_start.setEnabled(not check)
  759. self.ui.act_engine_stop.setEnabled(check)
  760. self.ui.frame_transport.setEnabled(check)
  761. @pyqtSlot()
  762. def slot_pluginAdd(self):
  763. dialog = PluginDatabaseW(self)
  764. if dialog.exec_():
  765. btype = dialog.fRetPlugin['build']
  766. ptype = dialog.fRetPlugin['type']
  767. filename = dialog.fRetPlugin['binary']
  768. label = dialog.fRetPlugin['label']
  769. extraStuff = self.getExtraStuff(dialog.fRetPlugin)
  770. self.addPlugin(btype, ptype, filename, None, label, extraStuff)
  771. @pyqtSlot()
  772. def slot_pluginRemoveAll(self):
  773. self.removeAllPlugins()
  774. self.connect(self.ui.ch_transport, SIGNAL("currentIndexChanged(int)"), SLOT("(int)"))
  775. self.connect(self.ui.b_transport_play, SIGNAL("clicked(bool)"), SLOT("(bool)"))
  776. self.connect(self.ui.b_transport_stop, SIGNAL("clicked()"), SLOT("()"))
  777. @pyqtSlot(int)
  778. def slot_transportModeChanged(self, newMode):
  779. Carla.host.set_engine_option(OPTION_TRANSPORT_MODE, newMode, "")
  780. @pyqtSlot(bool)
  781. def slot_transportPlayPause(self, toggled):
  782. if toggled:
  783. Carla.host.transport_play()
  784. else:
  785. Carla.host.transport_pause()
  786. @pyqtSlot()
  787. def slot_transportStop(self):
  788. Carla.host.transport_pause()
  789. Carla.host.transport_relocate(0)
  790. @pyqtSlot()
  791. def slot_aboutCarla(self):
  792. CarlaAboutW(self).exec_()
  793. @pyqtSlot()
  794. def slot_configureCarla(self):
  795. dialog = CarlaSettingsW(self)
  796. if dialog.exec_():
  797. self.loadSettings(False)
  798. for pwidget in self.fPluginList:
  799. if pwidget is None:
  800. return
  801. pwidget.setRefreshRate(self.fSavedSettings["Main/RefreshInterval"])
  802. @pyqtSlot()
  803. def slot_handleSIGUSR1(self):
  804. print("Got SIGUSR1 -> Saving project now")
  805. QTimer.singleShot(0, self, SLOT("slot_fileSave()"))
  806. @pyqtSlot()
  807. def slot_handleSIGTERM(self):
  808. print("Got SIGTERM -> Closing now")
  809. self.close()
  810. @pyqtSlot(int, int, int, float, str)
  811. def slot_handleDebugCallback(self, pluginId, value1, value2, value3, valueStr):
  812. print("DEBUG :: %i, %i, %i, %f, \"%s\")" % (pluginId, value1, value2, value3, valueStr))
  813. @pyqtSlot(int)
  814. def slot_handlePluginAddedCallback(self, pluginId):
  815. pwidget = PluginWidget(self, pluginId)
  816. pwidget.setRefreshRate(self.fSavedSettings["Main/RefreshInterval"])
  817. self.ui.w_plugins.layout().addWidget(pwidget)
  818. self.fPluginCount += 1
  819. self.fPluginList[pluginId] = pwidget
  820. if not self.fProjectLoading:
  821. pwidget.setActive(True, True, True)
  822. if self.fPluginCount == 1:
  823. self.ui.act_plugin_remove_all.setEnabled(True)
  824. @pyqtSlot(int)
  825. def slot_handlePluginRemovedCallback(self, pluginId):
  826. if pluginId >= self.fPluginCount:
  827. return
  828. pwidget = self.fPluginList[pluginId]
  829. if pwidget is None:
  830. return
  831. self.fPluginList[pluginId] = None
  832. self.fPluginCount -= 1
  833. self.ui.w_plugins.layout().removeWidget(pwidget)
  834. pwidget.ui.edit_dialog.close()
  835. pwidget.close()
  836. pwidget.deleteLater()
  837. del pwidget
  838. # push all plugins 1 slot back
  839. for i in range(pluginId, self.fPluginCount):
  840. self.fPluginList[i] = self.fPluginList[i+1]
  841. self.fPluginList[i].setId(i)
  842. if self.fPluginCount == 0:
  843. self.ui.act_plugin_remove_all.setEnabled(False)
  844. @pyqtSlot(int, str)
  845. def slot_handlePluginRenamedCallback(self, pluginId, newName):
  846. if pluginId >= self.fPluginCount:
  847. return
  848. pwidget = self.fPluginList[pluginId]
  849. if pwidget is None:
  850. return
  851. pwidget.ui.label_name.setText(newName)
  852. @pyqtSlot(int, int, float)
  853. def slot_handleParameterValueChangedCallback(self, pluginId, parameterId, value):
  854. if pluginId >= self.fPluginCount:
  855. return
  856. pwidget = self.fPluginList[pluginId]
  857. if pwidget is None:
  858. return
  859. pwidget.setParameterValue(parameterId, value)
  860. @pyqtSlot(int, int, float)
  861. def slot_handleParameterDefaultChangedCallback(self, pluginId, parameterId, value):
  862. if pluginId >= self.fPluginCount:
  863. return
  864. pwidget = self.fPluginList[pluginId]
  865. if pwidget is None:
  866. return
  867. pwidget.setParameterDefault(parameterId, value)
  868. @pyqtSlot(int, int, int)
  869. def slot_handleParameterMidiChannelChangedCallback(self, pluginId, parameterId, channel):
  870. if pluginId >= self.fPluginCount:
  871. return
  872. pwidget = self.fPluginList[pluginId]
  873. if pwidget is None:
  874. return
  875. pwidget.setParameterMidiChannel(parameterId, channel)
  876. @pyqtSlot(int, int, int)
  877. def slot_handleParameterMidiCcChangedCallback(self, pluginId, parameterId, cc):
  878. if pluginId >= self.fPluginCount:
  879. return
  880. pwidget = self.fPluginList[pluginId]
  881. if pwidget is None:
  882. return
  883. pwidget.setParameterMidiControl(parameterId, cc)
  884. @pyqtSlot(int, int)
  885. def slot_handleProgramChangedCallback(self, pluginId, programId):
  886. if pluginId >= self.fPluginCount:
  887. return
  888. pwidget = self.fPluginList[pluginId]
  889. if pwidget is None:
  890. return
  891. pwidget.setProgram(programId)
  892. @pyqtSlot(int, int)
  893. def slot_handleMidiProgramChangedCallback(self, pluginId, midiProgramId):
  894. if pluginId >= self.fPluginCount:
  895. return
  896. pwidget = self.fPluginList[pluginId]
  897. if pwidget is None:
  898. return
  899. pwidget.setMidiProgram(midiProgramId)
  900. @pyqtSlot(int, int, int, int)
  901. def slot_handleNoteOnCallback(self, pluginId, channel, note, velo):
  902. if pluginId >= self.fPluginCount:
  903. return
  904. pwidget = self.fPluginList[pluginId]
  905. if pwidget is None:
  906. return
  907. pwidget.sendNoteOn(channel, note)
  908. @pyqtSlot(int, int, int)
  909. def slot_handleNoteOffCallback(self, pluginId, channel, note):
  910. if pluginId >= self.fPluginCount:
  911. return
  912. pwidget = self.fPluginList[pluginId]
  913. if pwidget is None:
  914. return
  915. pwidget.sendNoteOff(channel, note)
  916. @pyqtSlot(int, int)
  917. def slot_handleShowGuiCallback(self, pluginId, show):
  918. if pluginId >= self.fPluginCount:
  919. return
  920. pwidget = self.fPluginList[pluginId]
  921. if pwidget is None:
  922. return
  923. if show == 0:
  924. pwidget.ui.b_gui.setChecked(False)
  925. pwidget.ui.b_gui.setEnabled(True)
  926. elif show == 1:
  927. pwidget.ui.b_gui.setChecked(True)
  928. pwidget.ui.b_gui.setEnabled(True)
  929. elif show == -1:
  930. pwidget.ui.b_gui.setChecked(False)
  931. pwidget.ui.b_gui.setEnabled(False)
  932. @pyqtSlot(int)
  933. def slot_handleUpdateCallback(self, pluginId):
  934. if pluginId >= self.fPluginCount:
  935. return
  936. pwidget = self.fPluginList[pluginId]
  937. if pwidget is None:
  938. return
  939. pwidget.ui.edit_dialog.updateInfo()
  940. @pyqtSlot(int)
  941. def slot_handleReloadInfoCallback(self, pluginId):
  942. if pluginId >= self.fPluginCount:
  943. return
  944. pwidget = self.fPluginList[pluginId]
  945. if pwidget is None:
  946. return
  947. pwidget.ui.edit_dialog.reloadInfo()
  948. @pyqtSlot(int)
  949. def slot_handleReloadParametersCallback(self, pluginId):
  950. if pluginId >= self.fPluginCount:
  951. return
  952. pwidget = self.fPluginList[pluginId]
  953. if pwidget is None:
  954. return
  955. pwidget.ui.edit_dialog.reloadParameters()
  956. @pyqtSlot(int)
  957. def slot_handleReloadProgramsCallback(self, pluginId):
  958. if pluginId >= self.fPluginCount:
  959. return
  960. pwidget = self.fPluginList[pluginId]
  961. if pwidget is None:
  962. return
  963. pwidget.ui.edit_dialog.reloadPrograms()
  964. @pyqtSlot(int)
  965. def slot_handleReloadAllCallback(self, pluginId):
  966. if pluginId >= self.fPluginCount:
  967. return
  968. pwidget = self.fPluginList[pluginId]
  969. if pwidget is None:
  970. return
  971. pwidget.ui.edit_dialog.reloadAll()
  972. @pyqtSlot(int, str)
  973. def slot_handlePatchbayClientAddedCallback(self, clientId, clientName):
  974. patchcanvas.addGroup(clientId, clientName)
  975. @pyqtSlot(int)
  976. def slot_handlePatchbayClientRemovedCallback(self, clientId):
  977. patchcanvas.removeGroup(clientId)
  978. @pyqtSlot(int, str)
  979. def slot_handlePatchbayClientRenamedCallback(self, clientId, newClientName):
  980. patchcanvas.renameGroup(clientId, newClientName)
  981. @pyqtSlot(int, int, int, str)
  982. def slot_handlePatchbayPortAddedCallback(self, clientId, portId, portFlags, portName):
  983. if (portFlags & PATCHBAY_PORT_IS_INPUT):
  984. portMode = patchcanvas.PORT_MODE_INPUT
  985. elif (portFlags & PATCHBAY_PORT_IS_OUTPUT):
  986. portMode = patchcanvas.PORT_MODE_OUTPUT
  987. else:
  988. portMode = patchcanvas.PORT_MODE_NULL
  989. if (portFlags & PATCHBAY_PORT_IS_AUDIO):
  990. portType = patchcanvas.PORT_TYPE_AUDIO_JACK
  991. elif (portFlags & PATCHBAY_PORT_IS_MIDI):
  992. portType = patchcanvas.PORT_TYPE_MIDI_JACK
  993. else:
  994. portType = patchcanvas.PORT_TYPE_NULL
  995. patchcanvas.addPort(clientId, portId, portName, portMode, portType)
  996. @pyqtSlot(int)
  997. def slot_handlePatchbayPortRemovedCallback(self, portId):
  998. patchcanvas.removePort(portId)
  999. @pyqtSlot(int, str)
  1000. def slot_handlePatchbayPortRenamedCallback(self, portId, newPortName):
  1001. patchcanvas.renamePort(portId, newPortName)
  1002. @pyqtSlot(int, int, int)
  1003. def slot_handlePatchbayConnectionAddedCallback(self, connectionId, portOutId, portInId):
  1004. patchcanvas.connectPorts(connectionId, portOutId, portInId)
  1005. @pyqtSlot(int)
  1006. def slot_handlePatchbayConnectionRemovedCallback(self, connectionId):
  1007. patchcanvas.disconnectPorts(connectionId)
  1008. @pyqtSlot(str)
  1009. def slot_handleErrorCallback(self, error):
  1010. QMessageBox.critical(self, self.tr("Error"), error)
  1011. @pyqtSlot()
  1012. def slot_handleQuitCallback(self):
  1013. CustomMessageBox(self, QMessageBox.Warning, self.tr("Warning"),
  1014. self.tr("Engine has been stopped or crashed.\nPlease restart Carla"),
  1015. self.tr("You may want to save your session now..."), QMessageBox.Ok, QMessageBox.Ok)
  1016. def getExtraStuff(self, plugin):
  1017. ptype = plugin['type']
  1018. if ptype == PLUGIN_LADSPA:
  1019. uniqueId = plugin['uniqueId']
  1020. for rdfItem in self.fLadspaRdfList:
  1021. if rdfItem.UniqueID == uniqueId:
  1022. return pointer(rdfItem)
  1023. elif ptype == PLUGIN_DSSI:
  1024. if (plugin['hints'] & PLUGIN_HAS_GUI):
  1025. gui = findDSSIGUI(plugin['binary'], plugin['name'], plugin['label'])
  1026. if gui:
  1027. return gui.encode("utf-8")
  1028. elif ptype == PLUGIN_SF2:
  1029. if plugin['name'].endswith(" (16 outputs)"):
  1030. # return a dummy non-null pointer
  1031. INTPOINTER = POINTER(c_int)
  1032. ptr = c_int(0x1)
  1033. addr = addressof(ptr)
  1034. return cast(addr, INTPOINTER)
  1035. return c_nullptr
  1036. def loadRDFs(self):
  1037. # Save RDF info for later
  1038. self.fLadspaRdfList = []
  1039. if not haveLRDF:
  1040. return
  1041. settingsDir = os.path.join(HOME, ".config", "Cadence")
  1042. frLadspaFile = os.path.join(settingsDir, "ladspa_rdf.db")
  1043. if os.path.exists(frLadspaFile):
  1044. frLadspa = open(frLadspaFile, 'r')
  1045. try:
  1046. self.fLadspaRdfList = ladspa_rdf.get_c_ladspa_rdfs(json.load(frLadspa))
  1047. except:
  1048. pass
  1049. frLadspa.close()
  1050. def saveSettings(self):
  1051. settings = QSettings()
  1052. settings.setValue("Geometry", self.saveGeometry())
  1053. settings.setValue("ShowToolbar", self.ui.toolBar.isVisible())
  1054. settings.setValue("ShowTransport", self.ui.frame_transport.isVisible())
  1055. settings.setValue("HorizontalScrollBarValue", self.ui.graphicsView.horizontalScrollBar().value())
  1056. settings.setValue("VerticalScrollBarValue", self.ui.graphicsView.verticalScrollBar().value())
  1057. def loadSettings(self, geometry):
  1058. settings = QSettings()
  1059. if geometry:
  1060. self.restoreGeometry(settings.value("Geometry", ""))
  1061. showToolbar = settings.value("ShowToolbar", True, type=bool)
  1062. self.ui.act_settings_show_toolbar.setChecked(showToolbar)
  1063. self.ui.toolBar.setVisible(showToolbar)
  1064. showTransport = settings.value("ShowTransport", True, type=bool)
  1065. self.ui.act_settings_show_transport.setChecked(showTransport)
  1066. self.ui.frame_transport.setVisible(showTransport)
  1067. self.fSavedSettings = {
  1068. "Main/DefaultProjectFolder": settings.value("Main/DefaultProjectFolder", HOME, type=str),
  1069. "Main/RefreshInterval": settings.value("Main/RefreshInterval", 50, type=int),
  1070. "Canvas/Theme": settings.value("Canvas/Theme", patchcanvas.getDefaultThemeName(), type=str),
  1071. "Canvas/AutoHideGroups": settings.value("Canvas/AutoHideGroups", False, type=bool),
  1072. "Canvas/UseBezierLines": settings.value("Canvas/UseBezierLines", True, type=bool),
  1073. "Canvas/EyeCandy": settings.value("Canvas/EyeCandy", patchcanvas.EYECANDY_SMALL, type=int),
  1074. "Canvas/UseOpenGL": settings.value("Canvas/UseOpenGL", False, type=bool),
  1075. "Canvas/Antialiasing": settings.value("Canvas/Antialiasing", patchcanvas.ANTIALIASING_SMALL, type=int),
  1076. "Canvas/HighQualityAntialiasing": settings.value("Canvas/HighQualityAntialiasing", False, type=bool)
  1077. }
  1078. # ---------------------------------------------
  1079. # plugin checks
  1080. if settings.value("Engine/DisableChecks", False, type=bool):
  1081. os.environ["CARLA_DISCOVERY_NO_PROCESSING_CHECKS"] = "true"
  1082. elif os.getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS"):
  1083. os.environ.pop("CARLA_DISCOVERY_NO_PROCESSING_CHECKS")
  1084. # ---------------------------------------------
  1085. # plugin paths
  1086. Carla.LADSPA_PATH = toList(settings.value("Paths/LADSPA", Carla.LADSPA_PATH))
  1087. Carla.DSSI_PATH = toList(settings.value("Paths/DSSI", Carla.DSSI_PATH))
  1088. Carla.LV2_PATH = toList(settings.value("Paths/LV2", Carla.LV2_PATH))
  1089. Carla.VST_PATH = toList(settings.value("Paths/VST", Carla.VST_PATH))
  1090. Carla.GIG_PATH = toList(settings.value("Paths/GIG", Carla.GIG_PATH))
  1091. Carla.SF2_PATH = toList(settings.value("Paths/SF2", Carla.SF2_PATH))
  1092. Carla.SFZ_PATH = toList(settings.value("Paths/SFZ", Carla.SFZ_PATH))
  1093. os.environ["LADSPA_PATH"] = splitter.join(Carla.LADSPA_PATH)
  1094. os.environ["DSSI_PATH"] = splitter.join(Carla.DSSI_PATH)
  1095. os.environ["LV2_PATH"] = splitter.join(Carla.LV2_PATH)
  1096. os.environ["VST_PATH"] = splitter.join(Carla.VST_PATH)
  1097. os.environ["GIG_PATH"] = splitter.join(Carla.GIG_PATH)
  1098. os.environ["SF2_PATH"] = splitter.join(Carla.SF2_PATH)
  1099. os.environ["SFZ_PATH"] = splitter.join(Carla.SFZ_PATH)
  1100. def resizeEvent(self, event):
  1101. if self.ui.tabWidget.currentIndex() == 0:
  1102. # Force update of 2nd tab
  1103. width = self.ui.tab_plugins.width()-4
  1104. height = self.ui.tab_plugins.height()-4
  1105. self.ui.miniCanvasPreview.setViewSize(float(width) / DEFAULT_CANVAS_WIDTH, float(height) / DEFAULT_CANVAS_HEIGHT)
  1106. else:
  1107. QTimer.singleShot(0, self, SLOT("slot_miniCanvasCheckSize()"))
  1108. QMainWindow.resizeEvent(self, event)
  1109. def timerEvent(self, event):
  1110. if event.timerId() == self.fIdleTimerFast:
  1111. Carla.host.engine_idle()
  1112. for pwidget in self.fPluginList:
  1113. if pwidget is None:
  1114. break
  1115. pwidget.idleFast()
  1116. elif event.timerId() == self.fIdleTimerSlow:
  1117. for pwidget in self.fPluginList:
  1118. if pwidget is None:
  1119. break
  1120. pwidget.idleSlow()
  1121. QMainWindow.timerEvent(self, event)
  1122. def closeEvent(self, event):
  1123. #if self.nsm_server:
  1124. #self.nsm_server.stop()
  1125. self.saveSettings()
  1126. if Carla.host.is_engine_running():
  1127. Carla.host.set_engine_about_to_close()
  1128. self.removeAllPlugins()
  1129. self.stopEngine()
  1130. QMainWindow.closeEvent(self, event)
  1131. # ------------------------------------------------------------------------------------------------
  1132. def canvasCallback(action, value1, value2, valueStr):
  1133. if action == patchcanvas.ACTION_GROUP_INFO:
  1134. pass
  1135. elif action == patchcanvas.ACTION_GROUP_RENAME:
  1136. pass
  1137. elif action == patchcanvas.ACTION_GROUP_SPLIT:
  1138. groupId = value1
  1139. patchcanvas.splitGroup(groupId)
  1140. elif action == patchcanvas.ACTION_GROUP_JOIN:
  1141. groupId = value1
  1142. patchcanvas.joinGroup(groupId)
  1143. elif action == patchcanvas.ACTION_PORT_INFO:
  1144. pass
  1145. elif action == patchcanvas.ACTION_PORT_RENAME:
  1146. pass
  1147. elif action == patchcanvas.ACTION_PORTS_CONNECT:
  1148. portIdA = value1
  1149. portIdB = value2
  1150. Carla.host.patchbay_connect(portIdA, portIdB)
  1151. elif action == patchcanvas.ACTION_PORTS_DISCONNECT:
  1152. connectionId = value1
  1153. Carla.host.patchbay_disconnect(connectionId)
  1154. def engineCallback(ptr, action, pluginId, value1, value2, value3, valueStr):
  1155. if pluginId < 0 or not Carla.gui:
  1156. return
  1157. if action == CALLBACK_DEBUG:
  1158. Carla.gui.emit(SIGNAL("DebugCallback(int, int, int, double, QString)"), pluginId, value1, value2, value3, cString(valueStr))
  1159. elif action == CALLBACK_PLUGIN_ADDED:
  1160. Carla.gui.emit(SIGNAL("PluginAddedCallback(int)"), pluginId)
  1161. elif action == CALLBACK_PLUGIN_REMOVED:
  1162. Carla.gui.emit(SIGNAL("PluginRemovedCallback(int)"), pluginId)
  1163. elif action == CALLBACK_PLUGIN_RENAMED:
  1164. Carla.gui.emit(SIGNAL("PluginRenamedCallback(int, QString)"), pluginId, valueStr)
  1165. elif action == CALLBACK_PARAMETER_VALUE_CHANGED:
  1166. Carla.gui.emit(SIGNAL("ParameterValueChangedCallback(int, int, double)"), pluginId, value1, value3)
  1167. elif action == CALLBACK_PARAMETER_DEFAULT_CHANGED:
  1168. Carla.gui.emit(SIGNAL("ParameterDefaultChangedCallback(int, int, double)"), pluginId, value1, value3)
  1169. elif action == CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED:
  1170. Carla.gui.emit(SIGNAL("ParameterMidiChannelChangedCallback(int, int, int)"), pluginId, value1, value2)
  1171. elif action == CALLBACK_PARAMETER_MIDI_CC_CHANGED:
  1172. Carla.gui.emit(SIGNAL("ParameterMidiCcChangedCallback(int, int, int)"), pluginId, value1, value2)
  1173. elif action == CALLBACK_PROGRAM_CHANGED:
  1174. Carla.gui.emit(SIGNAL("ProgramChangedCallback(int, int)"), pluginId, value1)
  1175. elif action == CALLBACK_MIDI_PROGRAM_CHANGED:
  1176. Carla.gui.emit(SIGNAL("MidiProgramChangedCallback(int, int)"), pluginId, value1)
  1177. elif action == CALLBACK_NOTE_ON:
  1178. Carla.gui.emit(SIGNAL("NoteOnCallback(int, int, int, int)"), pluginId, value1, value2, value3)
  1179. elif action == CALLBACK_NOTE_OFF:
  1180. Carla.gui.emit(SIGNAL("NoteOffCallback(int, int, int)"), pluginId, value1, value2)
  1181. elif action == CALLBACK_SHOW_GUI:
  1182. Carla.gui.emit(SIGNAL("ShowGuiCallback(int, int)"), pluginId, value1)
  1183. elif action == CALLBACK_UPDATE:
  1184. Carla.gui.emit(SIGNAL("UpdateCallback(int)"), pluginId)
  1185. elif action == CALLBACK_RELOAD_INFO:
  1186. Carla.gui.emit(SIGNAL("ReloadInfoCallback(int)"), pluginId)
  1187. elif action == CALLBACK_RELOAD_PARAMETERS:
  1188. Carla.gui.emit(SIGNAL("ReloadParametersCallback(int)"), pluginId)
  1189. elif action == CALLBACK_RELOAD_PROGRAMS:
  1190. Carla.gui.emit(SIGNAL("ReloadProgramsCallback(int)"), pluginId)
  1191. elif action == CALLBACK_RELOAD_ALL:
  1192. Carla.gui.emit(SIGNAL("ReloadAllCallback(int)"), pluginId)
  1193. elif action == CALLBACK_PATCHBAY_CLIENT_ADDED:
  1194. Carla.gui.emit(SIGNAL("PatchbayClientAddedCallback(int, QString)"), value1, cString(valueStr))
  1195. elif action == CALLBACK_PATCHBAY_CLIENT_REMOVED:
  1196. Carla.gui.emit(SIGNAL("PatchbayClientRemovedCallback(int)"), value1)
  1197. elif action == CALLBACK_PATCHBAY_CLIENT_RENAMED:
  1198. Carla.gui.emit(SIGNAL("PatchbayClientRenamedCallback(int, QString)"), value1, cString(valueStr))
  1199. elif action == CALLBACK_PATCHBAY_PORT_ADDED:
  1200. Carla.gui.emit(SIGNAL("PatchbayPortAddedCallback(int, int, int, QString)"), value1, value2, value3, cString(valueStr))
  1201. elif action == CALLBACK_PATCHBAY_PORT_REMOVED:
  1202. Carla.gui.emit(SIGNAL("PatchbayPortRemovedCallback(int)"), value1)
  1203. elif action == CALLBACK_PATCHBAY_PORT_RENAMED:
  1204. Carla.gui.emit(SIGNAL("PatchbayPortRenamedCallback(int, QString)"), value1, cString(valueStr))
  1205. elif action == CALLBACK_PATCHBAY_CONNECTION_ADDED:
  1206. Carla.gui.emit(SIGNAL("PatchbayConnectionAddedCallback(int, int, int)"), value1, value2, value3)
  1207. elif action == CALLBACK_PATCHBAY_CONNECTION_REMOVED:
  1208. Carla.gui.emit(SIGNAL("PatchbayConnectionRemovedCallback(int)"), value1)
  1209. #elif action == CALLBACK_NSM_ANNOUNCE:
  1210. #Carla.gui._nsmAnnounce2str = cString(Carla.host.get_last_error())
  1211. #Carla.gui.emit(SIGNAL("NSM_AnnounceCallback()"))
  1212. #elif action == CALLBACK_NSM_OPEN1:
  1213. #Carla.gui._nsmOpen1str = cString(valueStr)
  1214. #Carla.gui.emit(SIGNAL("NSM_Open1Callback()"))
  1215. #elif action == CALLBACK_NSM_OPEN2:
  1216. #Carla.gui._nsmOpen2str = cString(valueStr)
  1217. #Carla.gui.emit(SIGNAL("NSM_Open2Callback()"))
  1218. #elif action == CALLBACK_NSM_SAVE:
  1219. #Carla.gui.emit(SIGNAL("NSM_SaveCallback()"))
  1220. elif action == CALLBACK_ERROR:
  1221. Carla.gui.emit(SIGNAL("ErrorCallback(QString)"), cString(valueStr))
  1222. elif action == CALLBACK_QUIT:
  1223. Carla.gui.emit(SIGNAL("QuitCallback()"))
  1224. #--------------- main ------------------
  1225. if __name__ == '__main__':
  1226. # App initialization
  1227. app = QApplication(sys.argv)
  1228. app.setApplicationName("Carla")
  1229. app.setApplicationVersion(VERSION)
  1230. app.setOrganizationName("Cadence")
  1231. app.setWindowIcon(QIcon(":/scalable/carla.svg"))
  1232. libPrefix = None
  1233. projectFilename = None
  1234. for i in range(len(app.arguments())):
  1235. if i == 0: continue
  1236. argument = app.arguments()[i]
  1237. if argument.startswith("--with-libprefix="):
  1238. libPrefix = argument.replace("--with-libprefix=", "")
  1239. elif os.path.exists(argument):
  1240. projectFilename = argument
  1241. # Init backend
  1242. Carla.host = Host(libPrefix)
  1243. Carla.host.set_engine_callback(engineCallback)
  1244. Carla.host.set_engine_option(OPTION_PROCESS_NAME, 0, "carla")
  1245. # Set bridge paths
  1246. if carla_bridge_native:
  1247. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_NATIVE, 0, carla_bridge_native)
  1248. if carla_bridge_posix32:
  1249. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_POSIX32, 0, carla_bridge_posix32)
  1250. if carla_bridge_posix64:
  1251. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_POSIX64, 0, carla_bridge_posix64)
  1252. if carla_bridge_win32:
  1253. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_WIN32, 0, carla_bridge_win32)
  1254. if carla_bridge_win64:
  1255. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_WIN64, 0, carla_bridge_win64)
  1256. if WINDOWS:
  1257. if carla_bridge_lv2_windows:
  1258. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_WINDOWS, 0, carla_bridge_lv2_windows)
  1259. if carla_bridge_vst_hwnd:
  1260. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_VST_HWND, 0, carla_bridge_vst_hwnd)
  1261. elif MACOS:
  1262. if carla_bridge_lv2_cocoa:
  1263. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_COCOA, 0, carla_bridge_lv2_cocoa)
  1264. if carla_bridge_vst_cocoa:
  1265. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_VST_COCOA, 0, carla_bridge_vst_cocoa)
  1266. else:
  1267. if carla_bridge_lv2_gtk2:
  1268. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_GTK2, 0, carla_bridge_lv2_gtk2)
  1269. if carla_bridge_lv2_gtk3:
  1270. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_GTK3, 0, carla_bridge_lv2_gtk3)
  1271. if carla_bridge_lv2_qt4:
  1272. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_QT4, 0, carla_bridge_lv2_qt4)
  1273. if carla_bridge_lv2_qt5:
  1274. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_QT5, 0, carla_bridge_lv2_qt5)
  1275. if carla_bridge_lv2_x11:
  1276. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_X11, 0, carla_bridge_lv2_x11)
  1277. if carla_bridge_vst_x11:
  1278. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_VST_X11, 0, carla_bridge_vst_x11)
  1279. # Create GUI and start engine
  1280. Carla.gui = CarlaMainW()
  1281. # Set-up custom signal handling
  1282. setUpSignals()
  1283. # Show GUI
  1284. Carla.gui.show()
  1285. # Load project file if set
  1286. if projectFilename:
  1287. Carla.gui.loadProjectLater(projectFilename)
  1288. # App-Loop
  1289. ret = app.exec_()
  1290. # Exit properly
  1291. sys.exit(ret)