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