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_control.py 39KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla OSC controller
  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 QLibrary
  20. from PyQt4.QtGui import QApplication, QInputDialog, QMainWindow
  21. from liblo import make_method, Address, ServerError, ServerThread
  22. from liblo import send as lo_send
  23. from liblo import TCP as LO_TCP
  24. from liblo import UDP as LO_UDP
  25. # ------------------------------------------------------------------------------------------------------------
  26. # Imports (Custom)
  27. import ui_carla_control
  28. from carla_shared import *
  29. global lo_target, lo_targetName
  30. lo_target = None
  31. lo_targetName = ""
  32. Carla.isControl = True
  33. Carla.isLocal = False
  34. # ------------------------------------------------------------------------------------------------------------
  35. # Python Object dicts compatible to carla-backend struct ctypes
  36. ParameterData = {
  37. 'type': PARAMETER_NULL,
  38. 'index': 0,
  39. 'rindex': -1,
  40. 'hints': 0x0,
  41. 'midiChannel': 0,
  42. 'midiCC': -1
  43. }
  44. ParameterRanges = {
  45. 'def': 0.0,
  46. 'min': 0.0,
  47. 'max': 1.0,
  48. 'step': 0.0,
  49. 'stepSmall': 0.0,
  50. 'stepLarge': 0.0
  51. }
  52. MidiProgramData = {
  53. 'bank': 0,
  54. 'program': 0,
  55. 'name': None
  56. }
  57. CustomData = {
  58. 'type': CUSTOM_DATA_INVALID,
  59. 'key': None,
  60. 'value': None
  61. }
  62. # ------------------------------------------------------------------------------------------------------------
  63. CarlaPluginInfo = {
  64. 'type': PLUGIN_NONE,
  65. 'category': PLUGIN_CATEGORY_NONE,
  66. 'hints': 0x0,
  67. 'optionsAvailable': 0x0,
  68. 'optionsEnabled': 0x0,
  69. 'binary': None,
  70. 'name': None,
  71. 'label': None,
  72. 'maker': None,
  73. 'copyright': None,
  74. 'uniqueId': 0,
  75. 'latency': 0
  76. }
  77. CarlaNativePluginInfo = {
  78. 'category': PLUGIN_CATEGORY_NONE,
  79. 'hints': 0x0,
  80. 'audioIns': 0,
  81. 'audioOuts': 0,
  82. 'midiIns': 0,
  83. 'midiOuts': 0,
  84. 'parameterIns': 0,
  85. 'parameterOuts': 0,
  86. 'name': None,
  87. 'label': None,
  88. 'maker': None,
  89. 'copyright': None
  90. }
  91. CarlaPortCountInfo = {
  92. 'ins': 0,
  93. 'outs': 0,
  94. 'total': 0
  95. }
  96. CarlaParameterInfo = {
  97. 'name': None,
  98. 'symbol': None,
  99. 'unit': None,
  100. 'scalePointCount': 0,
  101. }
  102. CarlaScalePointInfo = {
  103. 'value': 0.0,
  104. 'label': None
  105. }
  106. CarlaTransportInfo = {
  107. 'playing': False,
  108. 'frame': 0,
  109. 'bar': 0,
  110. 'beat': 0,
  111. 'tick': 0,
  112. 'bpm': 0.0
  113. }
  114. # ------------------------------------------------------------------------------------------------------------
  115. # Helper class
  116. class ControlPluginInfo(object):
  117. __slots__ = [
  118. 'pluginInfo',
  119. 'pluginRealName',
  120. 'audioCountInfo',
  121. 'midiCountInfo',
  122. 'parameterCountInfo',
  123. 'parameterInfoS',
  124. 'parameterDataS',
  125. 'parameterRangeS',
  126. 'parameterValueS',
  127. 'programCount',
  128. 'programCurrent',
  129. 'programNameS',
  130. 'midiProgramCount',
  131. 'midiProgramCurrent',
  132. 'midiProgramDataS',
  133. 'inPeak',
  134. 'outPeak'
  135. ]
  136. # ------------------------------------------------------------------------------------------------------------
  137. # Python Object class compatible to 'Host' on the Carla Backend code
  138. class Host(object):
  139. def __init__(self):
  140. object.__init__(self)
  141. self.fPluginsInfo = []
  142. def _add(self, pluginId):
  143. if len(self.fPluginsInfo) != pluginId:
  144. return
  145. info = deepcopy(ControlPluginInfo)
  146. info.pluginInfo = CarlaPluginInfo
  147. info.pluginRealName = None
  148. info.audioCountInfo = CarlaPortCountInfo
  149. info.midiCountInfo = CarlaPortCountInfo
  150. info.parameterCountInfo = CarlaPortCountInfo
  151. info.parameterInfoS = []
  152. info.parameterDataS = []
  153. info.parameterRangeS = []
  154. info.parameterValueS = []
  155. info.programCount = 0
  156. info.programCurrent = -1
  157. info.programNameS = []
  158. info.midiProgramCount = 0
  159. info.midiProgramCurrent = -1
  160. info.midiProgramDataS = []
  161. info.peaks = [0.0, 0.0, 0.0, 0.0]
  162. self.fPluginsInfo.append(info)
  163. def _set_pluginInfo(self, index, info):
  164. self.fPluginsInfo[index].pluginInfo = info
  165. def _set_pluginRealName(self, index, realName):
  166. self.fPluginsInfo[index].pluginRealName = realName
  167. def _set_audioCountInfo(self, index, info):
  168. self.fPluginsInfo[index].audioCountInfo = info
  169. def _set_midiCountInfo(self, index, info):
  170. self.fPluginsInfo[index].midiCountInfo = info
  171. def _set_parameterCountInfo(self, index, info):
  172. self.fPluginsInfo[index].parameterCountInfo = info
  173. # clear
  174. self.fPluginsInfo[index].parameterInfoS = []
  175. self.fPluginsInfo[index].parameterDataS = []
  176. self.fPluginsInfo[index].parameterRangeS = []
  177. self.fPluginsInfo[index].parameterValueS = []
  178. # add placeholders
  179. for x in range(info['total']):
  180. self.fPluginsInfo[index].parameterInfoS.append(CarlaParameterInfo)
  181. self.fPluginsInfo[index].parameterDataS.append(ParameterData)
  182. self.fPluginsInfo[index].parameterRangeS.append(ParameterRanges)
  183. self.fPluginsInfo[index].parameterValueS.append(0.0)
  184. def _set_programCount(self, index, count):
  185. self.fPluginsInfo[index].programCount = count
  186. # clear
  187. self.fPluginsInfo[index].programNameS = []
  188. # add placeholders
  189. for x in range(count):
  190. self.fPluginsInfo[index].programNameS.append(None)
  191. def _set_midiProgramCount(self, index, count):
  192. self.fPluginsInfo[index].midiProgramCount = count
  193. # clear
  194. self.fPluginsInfo[index].midiProgramDataS = []
  195. # add placeholders
  196. for x in range(count):
  197. self.fPluginsInfo[index].midiProgramDataS.append(MidiProgramData)
  198. def _set_parameterInfoS(self, index, paramIndex, data):
  199. if paramIndex < self.fPluginsInfo[index].parameterCountInfo['total']:
  200. self.fPluginsInfo[index].parameterInfoS[paramIndex] = data
  201. def _set_parameterDataS(self, index, paramIndex, data):
  202. if paramIndex < self.fPluginsInfo[index].parameterCountInfo['total']:
  203. self.fPluginsInfo[index].parameterDataS[paramIndex] = data
  204. def _set_parameterRangeS(self, index, paramIndex, data):
  205. if paramIndex < self.fPluginsInfo[index].parameterCountInfo['total']:
  206. self.fPluginsInfo[index].parameterRangeS[paramIndex] = data
  207. def _set_parameterValueS(self, index, paramIndex, value):
  208. if paramIndex < self.fPluginsInfo[index].parameterCountInfo['total']:
  209. self.fPluginsInfo[index].parameterValueS[paramIndex] = value
  210. def _set_parameterDefaultValue(self, index, paramIndex, value):
  211. if paramIndex < self.fPluginsInfo[index].parameterCountInfo['total']:
  212. self.fPluginsInfo[index].parameterRangeS[paramIndex]['def'] = value
  213. def _set_parameterMidiCC(self, index, paramIndex, cc):
  214. if paramIndex < self.fPluginsInfo[index].parameterCountInfo['total']:
  215. self.fPluginsInfo[index].parameterDataS[paramIndex]['midiCC'] = cc
  216. def _set_parameterMidiChannel(self, index, paramIndex, channel):
  217. if paramIndex < self.fPluginsInfo[index].parameterCountInfo['total']:
  218. self.fPluginsInfo[index].parameterDataS[paramIndex]['midiChannel'] = channel
  219. def _set_currentProgram(self, index, pIndex):
  220. self.fPluginsInfo[index].programCurrent = pIndex
  221. def _set_currentMidiProgram(self, index, mpIndex):
  222. self.fPluginsInfo[index].midiProgramCurrent = mpIndex
  223. def _set_programNameS(self, index, pIndex, data):
  224. if pIndex < self.fPluginsInfo[index].programCount:
  225. self.fPluginsInfo[index].programNameS[pIndex] = data
  226. def _set_midiProgramDataS(self, index, mpIndex, data):
  227. if mpIndex < self.fPluginsInfo[index].midiProgramCount:
  228. self.fPluginsInfo[index].midiProgramDataS[mpIndex] = data
  229. def _set_peaks(self, index, in1, in2, out1, out2):
  230. self.fPluginsInfo[index].peaks = [in1, in2, out1, out2]
  231. # get_extended_license_text
  232. # get_supported_file_types
  233. # get_engine_driver_count
  234. # get_engine_driver_name
  235. # get_engine_driver_device_names
  236. # get_internal_plugin_count
  237. # get_internal_plugin_info
  238. # engine_init
  239. # engine_close
  240. # engine_idle
  241. # is_engine_running
  242. # set_engine_about_to_close
  243. # set_engine_callback
  244. # set_engine_option
  245. # load_filename
  246. # load_project
  247. # save_project
  248. # patchbay_connect
  249. # patchbay_disconnect
  250. # patchbay_refresh
  251. # transport_play
  252. # transport_pause
  253. # transport_relocate
  254. # get_current_transport_frame
  255. # get_transport_info
  256. # add_plugin
  257. # remove_plugin
  258. # remove_all_plugins
  259. # rename_plugin
  260. # clone_plugin
  261. # replace_plugin
  262. # switch_plugins
  263. # load_plugin_state
  264. # save_plugin_state
  265. def get_plugin_info(self, pluginId):
  266. return self.fPluginsInfo[pluginId].pluginInfo
  267. def get_audio_port_count_info(self, pluginId):
  268. return self.fPluginsInfo[pluginId].audioCountInfo
  269. def get_midi_port_count_info(self, pluginId):
  270. return self.fPluginsInfo[pluginId].midiCountInfo
  271. def get_parameter_count_info(self, pluginId):
  272. return self.fPluginsInfo[pluginId].parameterCountInfo
  273. def get_parameter_info(self, pluginId, parameterId):
  274. return self.fPluginsInfo[pluginId].parameterInfoS[parameterId]
  275. def get_parameter_scalepoint_info(self, pluginId, parameterId, scalepoint_id):
  276. return CarlaScalePointInfo
  277. def get_parameter_data(self, pluginId, parameterId):
  278. return self.fPluginsInfo[pluginId].parameterDataS[parameterId]
  279. def get_parameter_ranges(self, pluginId, parameterId):
  280. return self.fPluginsInfo[pluginId].parameterRangeS[parameterId]
  281. def get_midi_program_data(self, pluginId, midiProgramId):
  282. return self.fPluginsInfo[pluginId].midiProgramDataS[midiProgramId]
  283. def get_custom_data(self, pluginId, custom_data_id):
  284. return CustomData
  285. def get_chunk_data(self, pluginId):
  286. return None
  287. def get_parameter_count(self, pluginId):
  288. return self.fPluginsInfo[pluginId].parameterCountInfo['total']
  289. def get_program_count(self, pluginId):
  290. return self.fPluginsInfo[pluginId].programCount
  291. def get_midi_program_count(self, pluginId):
  292. return self.fPluginsInfo[pluginId].midiProgramCount
  293. def get_custom_data_count(self, pluginId):
  294. return 0
  295. def get_parameter_text(self, pluginId, parameterId):
  296. return None
  297. def get_program_name(self, pluginId, programId):
  298. return self.fPluginsInfo[pluginId].programNameS[programId]
  299. def get_midi_program_name(self, pluginId, midiProgramId):
  300. return self.fPluginsInfo[pluginId].midiProgramDataS[midiProgramId]['label']
  301. def get_real_plugin_name(self, pluginId):
  302. return self.fPluginsInfo[pluginId].pluginRealName
  303. def get_current_program_index(self, pluginId):
  304. return self.fPluginsInfo[pluginId].programCurrent
  305. def get_current_midi_program_index(self, pluginId):
  306. return self.fPluginsInfo[pluginId].midiProgramCurrent
  307. def get_default_parameter_value(self, pluginId, parameterId):
  308. return self.fPluginsInfo[pluginId].parameterRangeS[parameterId]['def']
  309. def get_current_parameter_value(self, pluginId, parameterId):
  310. return self.fPluginsInfo[pluginId].parameterValueS[parameterId]
  311. def get_input_peak_value(self, pluginId, portId):
  312. return self.fPluginsInfo[pluginId].peaks[portId-1]
  313. def get_output_peak_value(self, pluginId, portId):
  314. return self.fPluginsInfo[pluginId].peaks[2+portId-1]
  315. def set_option(self, pluginId, option, yesNo):
  316. global to_target, lo_targetName
  317. lo_path = "/%s/%i/set_option" % (lo_targetName, pluginId)
  318. lo_send(lo_target, lo_path, option, yesNo)
  319. def set_active(self, pluginId, onoff):
  320. global to_target, lo_targetName
  321. lo_path = "/%s/%i/set_active" % (lo_targetName, pluginId)
  322. lo_send(lo_target, lo_path, 1 if onoff else 0)
  323. def set_drywet(self, pluginId, value):
  324. global to_target, lo_targetName
  325. lo_path = "/%s/%i/set_drywet" % (lo_targetName, pluginId)
  326. lo_send(lo_target, lo_path, value)
  327. def set_volume(self, pluginId, value):
  328. global to_target, lo_targetName
  329. lo_path = "/%s/%i/set_volume" % (lo_targetName, pluginId)
  330. lo_send(lo_target, lo_path, value)
  331. def set_balance_left(self, pluginId, value):
  332. global to_target, lo_targetName
  333. lo_path = "/%s/%i/set_balance_left" % (lo_targetName, pluginId)
  334. lo_send(lo_target, lo_path, value)
  335. def set_balance_right(self, pluginId, value):
  336. global to_target, lo_targetName
  337. lo_path = "/%s/%i/set_balance_right" % (lo_targetName, pluginId)
  338. lo_send(lo_target, lo_path, value)
  339. def set_panning(self, pluginId, value):
  340. global to_target, lo_targetName
  341. lo_path = "/%s/%i/set_panning" % (lo_targetName, pluginId)
  342. lo_send(lo_target, lo_path, value)
  343. def set_ctrl_channel(self, pluginId, channel):
  344. global to_target, lo_targetName
  345. lo_path = "/%s/%i/set_ctrl_channel" % (lo_targetName, pluginId)
  346. lo_send(lo_target, lo_path, channel)
  347. def set_parameter_value(self, pluginId, parameterId, value):
  348. global to_target, lo_targetName
  349. lo_path = "/%s/%i/set_parameter_value" % (lo_targetName, pluginId)
  350. lo_send(lo_target, lo_path, parameterId, value)
  351. def set_parameter_midi_cc(self, pluginId, parameterId, midi_cc):
  352. global to_target, lo_targetName
  353. lo_path = "/%s/%i/set_parameter_midi_cc" % (lo_targetName, pluginId)
  354. lo_send(lo_target, lo_path, parameterId, midi_cc)
  355. def set_parameter_midi_channel(self, pluginId, parameterId, channel):
  356. global to_target, lo_targetName
  357. lo_path = "/%s/%i/set_parameter_midi_channel" % (lo_targetName, pluginId)
  358. lo_send(lo_target, lo_path, parameterId, channel)
  359. def set_program(self, pluginId, programId):
  360. global to_target, lo_targetName
  361. lo_path = "/%s/%i/set_program" % (lo_targetName, pluginId)
  362. lo_send(lo_target, lo_path, programId)
  363. def set_midi_program(self, pluginId, midiProgramId):
  364. global to_target, lo_targetName
  365. lo_path = "/%s/%i/set_midi_program" % (lo_targetName, pluginId)
  366. lo_send(lo_target, lo_path, midiProgramId)
  367. # set_custom_data
  368. # set_chunk_data
  369. # prepare_for_save
  370. def send_midi_note(self, pluginId, channel, note, velocity):
  371. global to_target, lo_targetName
  372. if velocity:
  373. lo_path = "/%s/%i/note_on" % (lo_targetName, pluginId)
  374. lo_send(lo_target, lo_path, channel, note, velocity)
  375. else:
  376. lo_path = "/%s/%i/note_off" % (lo_targetName, pluginId)
  377. lo_send(lo_target, lo_path, channel, note)
  378. # show_gui
  379. # get_buffer_size
  380. # get_sample_rate
  381. # get_last_error
  382. # get_host_osc_url
  383. # nsm_announce
  384. # nsm_reply_open
  385. # nsm_reply_save
  386. # ------------------------------------------------------------------------------------------------------------
  387. # OSC Control server
  388. class ControlServer(ServerThread):
  389. def __init__(self, parent, mode):
  390. ServerThread.__init__(self, 8087, mode)
  391. self.fParent = parent
  392. def getFullURL(self):
  393. return "%scarla-control" % self.get_url()
  394. @make_method('/carla-control/add_plugin_start', 'is')
  395. def add_plugin_start_callback(self, path, args):
  396. pluginId, pluginName = args
  397. self.fParent.emit(SIGNAL("AddPluginStart(int, QString)"), pluginId, pluginName)
  398. @make_method('/carla-control/add_plugin_end', 'i')
  399. def add_plugin_end_callback(self, path, args):
  400. pluginId, = args
  401. self.fParent.emit(SIGNAL("AddPluginEnd(int)"), pluginId)
  402. @make_method('/carla-control/remove_plugin', 'i')
  403. def remove_plugin_callback(self, path, args):
  404. pluginId, = args
  405. self.fParent.emit(SIGNAL("RemovePlugin(int)"), pluginId)
  406. @make_method('/carla-control/set_plugin_data', 'iiiissssh')
  407. def set_plugin_data_callback(self, path, args):
  408. pluginId, ptype, category, hints, realName, label, maker, copyright_, uniqueId = args
  409. self.fParent.emit(SIGNAL("SetPluginData(int, int, int, int, QString, QString, QString, QString, int)"), pluginId, ptype, category, hints, realName, label, maker, copyright_, uniqueId)
  410. @make_method('/carla-control/set_plugin_ports', 'iiiiiiii')
  411. def set_plugin_ports_callback(self, path, args):
  412. pluginId, audioIns, audioOuts, midiIns, midiOuts, cIns, cOuts, cTotals = args
  413. self.fParent.emit(SIGNAL("SetPluginPorts(int, int, int, int, int, int, int, int)"), pluginId, audioIns, audioOuts, midiIns, midiOuts, cIns, cOuts, cTotals)
  414. @make_method('/carla-control/set_parameter_data', 'iiiissf')
  415. def set_parameter_data_callback(self, path, args):
  416. pluginId, index, type_, hints, name, label, current = args
  417. self.fParent.emit(SIGNAL("SetParameterData(int, int, int, int, QString, QString, double)"), pluginId, index, type_, hints, name, label, current)
  418. @make_method('/carla-control/set_parameter_ranges', 'iiffffff')
  419. def set_parameter_ranges_callback(self, path, args):
  420. pluginId, index, min_, max_, def_, step, stepSmall, stepLarge = args
  421. self.fParent.emit(SIGNAL("SetParameterRanges(int, int, double, double, double, double, double, double)"), pluginId, index, min_, max_, def_, step, stepSmall, stepLarge)
  422. @make_method('/carla-control/set_parameter_midi_cc', 'iii')
  423. def set_parameter_midi_cc_callback(self, path, args):
  424. pluginId, index, cc = args
  425. self.fParent.emit(SIGNAL("SetParameterMidiCC(int, int, int)"), pluginId, index, cc)
  426. @make_method('/carla-control/set_parameter_midi_channel', 'iii')
  427. def set_parameter_midi_channel_callback(self, path, args):
  428. pluginId, index, channel = args
  429. self.fParent.emit(SIGNAL("SetParameterMidiChannel(int, int, int)"), pluginId, index, channel)
  430. @make_method('/carla-control/set_parameter_value', 'iif')
  431. def set_parameter_value_callback(self, path, args):
  432. pluginId, index, value = args
  433. self.fParent.emit(SIGNAL("SetParameterValue(int, int, double)"), pluginId, index, value)
  434. @make_method('/carla-control/set_default_value', 'iif')
  435. def set_default_value_callback(self, path, args):
  436. pluginId, index, value = args
  437. self.fParent.emit(SIGNAL("SetDefaultValue(int, int, double)"), pluginId, index, value)
  438. @make_method('/carla-control/set_program', 'ii')
  439. def set_program_callback(self, path, args):
  440. pluginId, index = args
  441. self.fParent.emit(SIGNAL("SetProgram(int, int)"), pluginId, index)
  442. @make_method('/carla-control/set_program_count', 'ii')
  443. def set_program_count_callback(self, path, args):
  444. pluginId, count = args
  445. self.fParent.emit(SIGNAL("SetProgramCount(int, int)"), pluginId, count)
  446. @make_method('/carla-control/set_program_name', 'iis')
  447. def set_program_name_callback(self, path, args):
  448. pluginId, index, name = args
  449. self.fParent.emit(SIGNAL("SetProgramName(int, int, QString)"), pluginId, index, name)
  450. @make_method('/carla-control/set_midi_program', 'ii')
  451. def set_midi_program_callback(self, path, args):
  452. pluginId, index = args
  453. self.fParent.emit(SIGNAL("SetMidiProgram(int, int)"), pluginId, index)
  454. @make_method('/carla-control/set_midi_program_count', 'ii')
  455. def set_midi_program_count_callback(self, path, args):
  456. pluginId, count = args
  457. self.fParent.emit(SIGNAL("SetMidiProgramCount(int, int)"), pluginId, count)
  458. @make_method('/carla-control/set_midi_program_data', 'iiiis')
  459. def set_midi_program_data_callback(self, path, args):
  460. pluginId, index, bank, program, name = args
  461. self.fParent.emit(SIGNAL("SetMidiProgramData(int, int, int, int, QString)"), pluginId, index, bank, program, name)
  462. @make_method('/carla-control/note_on', 'iiii')
  463. def note_on_callback(self, path, args):
  464. pluginId, channel, note, velo = args
  465. self.fParent.emit(SIGNAL("NoteOn(int, int, int, int)"), pluginId, channel, note, velo)
  466. @make_method('/carla-control/note_off', 'iii')
  467. def note_off_callback(self, path, args):
  468. pluginId, channel, note = args
  469. self.fParent.emit(SIGNAL("NoteOff(int, int, int)"), pluginId, channel, note)
  470. @make_method('/carla-control/set_peaks', 'iffff')
  471. def set_output_peak_value_callback(self, path, args):
  472. pluginId, in1, in2, out1, out2 = args
  473. self.fParent.emit(SIGNAL("SetPeaks(int, double, double, double, double)"), pluginId, in1, in2, out1, out2)
  474. @make_method('/carla-control/exit', '')
  475. def exit_callback(self, path, args):
  476. self.fParent.emit(SIGNAL("Exit()"))
  477. @make_method(None, None)
  478. def fallback(self, path, args):
  479. print("ControlServer::fallback(\"%s\") - unknown message, args =" % path, args)
  480. # ------------------------------------------------------------------------------------------------------------
  481. # Main Window
  482. class CarlaControlW(QMainWindow):
  483. def __init__(self, parent=None):
  484. QMainWindow.__init__(self, parent)
  485. self.ui = ui_carla_control.Ui_CarlaControlW()
  486. self.ui.setupUi(self)
  487. if MACOS:
  488. self.setUnifiedTitleAndToolBarOnMac(True)
  489. # -------------------------------------------------------------
  490. # Internal stuff
  491. self.fProjectFilename = None
  492. self.fProjectLoading = False
  493. self.fPluginCount = 0
  494. self.fPluginList = []
  495. self.fIdleTimerFast = 0
  496. self.fIdleTimerSlow = 0
  497. self.fLastPluginName = ""
  498. self.lo_address = ""
  499. self.lo_server = None
  500. # -------------------------------------------------------------
  501. # Load Settings
  502. self.loadSettings()
  503. # -------------------------------------------------------------
  504. # Set-up GUI stuff
  505. self.ui.act_file_refresh.setEnabled(False)
  506. #self.ui.act_plugin_remove_all.setEnabled(False)
  507. self.resize(self.width(), 0)
  508. # -------------------------------------------------------------
  509. # Connect actions to functions
  510. self.connect(self.ui.act_file_connect, SIGNAL("triggered()"), SLOT("slot_fileConnect()"))
  511. self.connect(self.ui.act_file_refresh, SIGNAL("triggered()"), SLOT("slot_fileRefresh()"))
  512. #self.connect(self.ui.act_plugin_add, SIGNAL("triggered()"), SLOT("slot_pluginAdd()"))
  513. #self.connect(self.ui.act_plugin_add2, SIGNAL("triggered()"), SLOT("slot_pluginAdd()"))
  514. #self.connect(self.ui.act_plugin_refresh, SIGNAL("triggered()"), SLOT("slot_pluginRefresh()"))
  515. #self.connect(self.ui.act_plugin_remove_all, SIGNAL("triggered()"), SLOT("slot_pluginRemoveAll()"))
  516. #self.connect(self.ui.act_settings_show_toolbar, SIGNAL("triggered(bool)"), SLOT("slot_toolbarShown()"))
  517. #self.connect(self.ui.act_settings_configure, SIGNAL("triggered()"), SLOT("slot_configureCarla()"))
  518. self.connect(self.ui.act_help_about, SIGNAL("triggered()"), SLOT("slot_aboutCarlaControl()"))
  519. self.connect(self.ui.act_help_about_qt, SIGNAL("triggered()"), app, SLOT("aboutQt()"))
  520. self.connect(self, SIGNAL("SIGTERM()"), SLOT("slot_handleSIGTERM()"))
  521. self.connect(self, SIGNAL("AddPluginStart(int, QString)"), SLOT("slot_handleAddPluginStart(int, QString)"))
  522. self.connect(self, SIGNAL("AddPluginEnd(int)"), SLOT("slot_handleAddPluginEnd(int)"))
  523. self.connect(self, SIGNAL("RemovePlugin(int)"), SLOT("slot_handleRemovePlugin(int)"))
  524. self.connect(self, SIGNAL("SetPluginData(int, int, int, int, QString, QString, QString, QString, int)"), SLOT("slot_handleSetPluginData(int, int, int, int, QString, QString, QString, QString, int)"))
  525. self.connect(self, SIGNAL("SetPluginPorts(int, int, int, int, int, int, int, int)"), SLOT("slot_handleSetPluginPorts(int, int, int, int, int, int, int, int)"))
  526. self.connect(self, SIGNAL("SetParameterData(int, int, int, int, QString, QString, double)"), SLOT("slot_handleSetParameterData(int, int, int, int, QString, QString, double)"))
  527. self.connect(self, SIGNAL("SetParameterRanges(int, int, double, double, double, double, double, double)"), SLOT("slot_handleSetParameterRanges(int, int, double, double, double, double, double, double)"))
  528. self.connect(self, SIGNAL("SetParameterMidiCC(int, int, int)"), SLOT("slot_handleSetParameterMidiCC(int, int, int)"))
  529. self.connect(self, SIGNAL("SetParameterMidiChannel(int, int, int)"), SLOT("slot_handleSetParameterMidiChannel(int, int, int)"))
  530. self.connect(self, SIGNAL("SetParameterValue(int, int, double)"), SLOT("slot_handleSetParameterValue(int, int, double)"))
  531. self.connect(self, SIGNAL("SetDefaultValue(int, int, double)"), SLOT("slot_handleSetDefaultValue(int, int, double)"))
  532. self.connect(self, SIGNAL("SetProgram(int, int)"), SLOT("slot_handleSetProgram(int, int)"))
  533. self.connect(self, SIGNAL("SetProgramCount(int, int)"), SLOT("slot_handleSetProgramCount(int, int)"))
  534. self.connect(self, SIGNAL("SetProgramName(int, int, QString)"), SLOT("slot_handleSetProgramName(int, int, QString)"))
  535. self.connect(self, SIGNAL("SetMidiProgram(int, int)"), SLOT("slot_handleSetMidiProgram(int, int)"))
  536. self.connect(self, SIGNAL("SetMidiProgramCount(int, int)"), SLOT("slot_handleSetMidiProgramCount(int, int)"))
  537. self.connect(self, SIGNAL("SetMidiProgramData(int, int, int, int, QString)"), SLOT("slot_handleSetMidiProgramData(int, int, int, int, QString)"))
  538. self.connect(self, SIGNAL("NoteOn(int, int, int, int)"), SLOT("slot_handleNoteOn(int, int, int, int)"))
  539. self.connect(self, SIGNAL("NoteOff(int, int, int)"), SLOT("slot_handleNoteOff(int, int, int)"))
  540. self.connect(self, SIGNAL("SetPeaks(int, double, double, double, double)"), SLOT("slot_handleSetPeaks(int, double, double, double, double)"))
  541. self.connect(self, SIGNAL("Exit()"), SLOT("slot_handleExit()"))
  542. def removeAll(self):
  543. self.killTimer(self.fIdleTimerFast)
  544. self.killTimer(self.fIdleTimerSlow)
  545. self.fIdleTimerFast = 0
  546. self.fIdleTimerSlow = 0
  547. for i in range(self.fPluginCount):
  548. pwidget = self.fPluginList[i]
  549. if pwidget is None:
  550. break
  551. pwidget.ui.edit_dialog.close()
  552. pwidget.close()
  553. pwidget.deleteLater()
  554. del pwidget
  555. self.fPluginCount = 0
  556. self.fPluginList = []
  557. Carla.host.fPluginsInfo = []
  558. self.fIdleTimerFast = self.startTimer(60)
  559. self.fIdleTimerSlow = self.startTimer(60*2)
  560. @pyqtSlot()
  561. def slot_handleSIGTERM(self):
  562. print("Got SIGTERM -> Closing now")
  563. self.close()
  564. @pyqtSlot()
  565. def slot_fileConnect(self):
  566. global lo_target, lo_targetName
  567. if lo_target and self.lo_server:
  568. urlText = self.lo_address
  569. else:
  570. urlText = "osc.tcp://127.0.0.1:19000/Carla"
  571. askValue = QInputDialog.getText(self, self.tr("Carla Control - Connect"), self.tr("Address"), text=urlText)
  572. if not askValue[1]:
  573. return
  574. self.slot_handleExit()
  575. self.lo_address = askValue[0]
  576. lo_target = Address(self.lo_address)
  577. lo_targetName = self.lo_address.rsplit("/", 1)[-1]
  578. print("Connecting to \"%s\" as '%s'..." % (self.lo_address, lo_targetName))
  579. try:
  580. self.lo_server = ControlServer(self, LO_UDP if self.lo_address.startswith("osc.udp") else LO_TCP)
  581. except: # ServerError, err:
  582. print("Connecting error!")
  583. #print str(err)
  584. QMessageBox.critical(self, self.tr("Error"), self.tr("Failed to connect, operation failed."))
  585. if self.lo_server:
  586. self.lo_server.start()
  587. self.ui.act_file_refresh.setEnabled(True)
  588. lo_send(lo_target, "/register", self.lo_server.getFullURL())
  589. @pyqtSlot()
  590. def slot_fileRefresh(self):
  591. global lo_target
  592. if lo_target and self.lo_server:
  593. self.removeAll()
  594. lo_send(lo_target, "/unregister")
  595. lo_send(lo_target, "/register", self.lo_server.getFullURL())
  596. @pyqtSlot()
  597. def slot_aboutCarlaControl(self):
  598. CarlaAboutW(self).exec_()
  599. @pyqtSlot(int, str)
  600. def slot_handleAddPluginStart(self, pluginId, pluginName):
  601. self.fLastPluginName = pluginName
  602. Carla.host._add(pluginId)
  603. @pyqtSlot(int)
  604. def slot_handleAddPluginEnd(self, pluginId):
  605. pwidget = PluginWidget(self, pluginId)
  606. self.ui.w_plugins.layout().addWidget(pwidget)
  607. self.fPluginCount += 1
  608. self.fPluginList.append(pwidget)
  609. @pyqtSlot(int)
  610. def slot_handleRemovePlugin(self, pluginId):
  611. if pluginId >= self.fPluginCount:
  612. print("handleRemovePlugin(%i) - invalid plugin id" % pluginId)
  613. return
  614. pwidget = self.fPluginList[pluginId]
  615. if pwidget is None:
  616. print("handleRemovePlugin(%i) - invalid plugin" % pluginId)
  617. return
  618. self.fPluginList.pop(pluginId)
  619. self.fPluginCount -= 1
  620. self.ui.w_plugins.layout().removeWidget(pwidget)
  621. pwidget.ui.edit_dialog.close()
  622. pwidget.close()
  623. pwidget.deleteLater()
  624. del pwidget
  625. # push all plugins 1 slot back
  626. for i in range(pluginId, self.fPluginCount):
  627. self.fPluginList[i].setId(i)
  628. Carla.host.fPluginsInfo.pop(pluginId)
  629. @pyqtSlot(int, int, int, int, str, str, str, str, int)
  630. def slot_handleSetPluginData(self, pluginId, type_, category, hints, realName, label, maker, copyright, uniqueId):
  631. info = deepcopy(CarlaPluginInfo)
  632. info['type'] = type_
  633. info['category'] = category
  634. info['hints'] = hints
  635. info['name'] = self.fLastPluginName
  636. info['label'] = label
  637. info['maker'] = maker
  638. info['copyright'] = copyright
  639. info['uniqueId'] = uniqueId
  640. Carla.host._set_pluginInfo(pluginId, info)
  641. Carla.host._set_pluginRealName(pluginId, realName)
  642. @pyqtSlot(int, int, int, int, int, int, int, int)
  643. def slot_handleSetPluginPorts(self, pluginId, audioIns, audioOuts, midiIns, midiOuts, cIns, cOuts, cTotals):
  644. audioInfo = deepcopy(CarlaPortCountInfo)
  645. midiInfo = deepcopy(CarlaPortCountInfo)
  646. paramInfo = deepcopy(CarlaPortCountInfo)
  647. audioInfo['ins'] = audioIns
  648. audioInfo['outs'] = audioOuts
  649. audioInfo['total'] = audioIns + audioOuts
  650. midiInfo['ins'] = midiIns
  651. midiInfo['outs'] = midiOuts
  652. midiInfo['total'] = midiIns + midiOuts
  653. paramInfo['ins'] = cIns
  654. paramInfo['outs'] = cOuts
  655. paramInfo['total'] = cTotals
  656. Carla.host._set_audioCountInfo(pluginId, audioInfo)
  657. Carla.host._set_midiCountInfo(pluginId, midiInfo)
  658. Carla.host._set_parameterCountInfo(pluginId, paramInfo)
  659. @pyqtSlot(int, int, int, int, str, str, float)
  660. def slot_handleSetParameterData(self, pluginId, index, type_, hints, name, label, current):
  661. # remove hints not possible in bridge mode
  662. hints &= ~(PARAMETER_USES_SCALEPOINTS | PARAMETER_USES_CUSTOM_TEXT)
  663. data = deepcopy(ParameterData)
  664. data['type'] = type_
  665. data['index'] = index
  666. data['rindex'] = index
  667. data['hints'] = hints
  668. info = deepcopy(CarlaParameterInfo)
  669. info['name'] = name
  670. info['label'] = label
  671. Carla.host._set_parameterDataS(pluginId, index, data)
  672. Carla.host._set_parameterInfoS(pluginId, index, info)
  673. Carla.host._set_parameterValueS(pluginId, index, current)
  674. @pyqtSlot(int, int, float, float, float, float, float, float)
  675. def slot_handleSetParameterRanges(self, pluginId, index, min_, max_, def_, step, stepSmall, stepLarge):
  676. ranges = deepcopy(ParameterRanges)
  677. ranges['min'] = min_
  678. ranges['max'] = max_
  679. ranges['def'] = def_
  680. ranges['step'] = step
  681. ranges['stepSmall'] = stepSmall
  682. ranges['stepLarge'] = stepLarge
  683. Carla.host._set_parameterRangeS(pluginId, index, ranges)
  684. @pyqtSlot(int, int, float)
  685. def slot_handleSetParameterValue(self, pluginId, parameterId, value):
  686. if parameterId >= 0:
  687. Carla.host._set_parameterValueS(pluginId, parameterId, value)
  688. if pluginId >= self.fPluginCount:
  689. return
  690. pwidget = self.fPluginList[pluginId]
  691. if pwidget is None:
  692. return
  693. pwidget.setParameterValue(parameterId, value)
  694. @pyqtSlot(int, int, float)
  695. def slot_handleSetDefaultValue(self, pluginId, parameterId, value):
  696. Carla.host._set_parameterDefaultValue(pluginId, parameterId, value)
  697. if pluginId >= self.fPluginCount:
  698. return
  699. pwidget = self.fPluginList[pluginId]
  700. if pwidget is None:
  701. return
  702. pwidget.setParameterDefault(parameterId, value)
  703. @pyqtSlot(int, int, int)
  704. def slot_handleSetParameterMidiCC(self, pluginId, index, cc):
  705. Carla.host._set_parameterMidiCC(pluginId, index, cc)
  706. if pluginId >= self.fPluginCount:
  707. return
  708. pwidget = self.fPluginList[pluginId]
  709. if pwidget is None:
  710. return
  711. pwidget.setParameterMidiControl(index, cc)
  712. @pyqtSlot(int, int, int)
  713. def slot_handleSetParameterMidiChannel(self, pluginId, index, channel):
  714. Carla.host._set_parameterMidiChannel(pluginId, index, channel)
  715. if pluginId >= self.fPluginCount:
  716. return
  717. pwidget = self.fPluginList[pluginId]
  718. if pwidget is None:
  719. return
  720. pwidget.setParameterMidiChannel(index, channel)
  721. @pyqtSlot(int, int)
  722. def slot_handleSetProgram(self, pluginId, index):
  723. Carla.host._set_currentProgram(pluginId, index)
  724. if pluginId >= self.fPluginCount:
  725. return
  726. pwidget = self.fPluginList[pluginId]
  727. if pwidget is None:
  728. return
  729. pwidget.setProgram(index)
  730. @pyqtSlot(int, int)
  731. def slot_handleSetProgramCount(self, pluginId, count):
  732. Carla.host._set_programCount(pluginId, count)
  733. @pyqtSlot(int, int, str)
  734. def slot_handleSetProgramName(self, pluginId, index, name):
  735. Carla.host._set_programNameS(pluginId, index, name)
  736. @pyqtSlot(int, int)
  737. def slot_handleSetMidiProgram(self, pluginId, index):
  738. Carla.host._set_currentMidiProgram(pluginId, index)
  739. if pluginId >= self.fPluginCount:
  740. return
  741. pwidget = self.fPluginList[pluginId]
  742. if pwidget is None:
  743. return
  744. pwidget.setMidiProgram(index)
  745. @pyqtSlot(int, int)
  746. def slot_handleSetMidiProgramCount(self, pluginId, count):
  747. Carla.host._set_midiProgramCount(pluginId, count)
  748. @pyqtSlot(int, int, int, int, str)
  749. def slot_handleSetMidiProgramData(self, pluginId, index, bank, program, name):
  750. data = deepcopy(MidiProgramData)
  751. data['bank'] = bank
  752. data['program'] = program
  753. data['label'] = name
  754. Carla.host._set_midiProgramDataS(pluginId, index, data)
  755. @pyqtSlot(int, int, float)
  756. def slot_handleSetInputPeakValue(self, pluginId, portId, value):
  757. Carla.host._set_inPeak(pluginId, portId-1, value)
  758. @pyqtSlot(int, int, float)
  759. def slot_handleSetOutputPeakValue(self, pluginId, portId, value):
  760. Carla.host._set_outPeak(pluginId, portId-1, value)
  761. @pyqtSlot(int, int, int, int)
  762. def slot_handleNoteOn(self, pluginId, channel, note, velo):
  763. if pluginId >= self.fPluginCount:
  764. return
  765. pwidget = self.fPluginList[pluginId]
  766. if pwidget is None:
  767. return
  768. pwidget.sendNoteOn(channel, note)
  769. @pyqtSlot(int, int, int)
  770. def slot_handleNoteOff(self, pluginId, channel, note):
  771. if pluginId >= self.fPluginCount:
  772. return
  773. pwidget = self.fPluginList[pluginId]
  774. if pwidget is None:
  775. return
  776. pwidget.sendNoteOff(channel, note)
  777. @pyqtSlot(int, float, float, float, float)
  778. def slot_handleSetPeaks(self, pluginId, in1, in2, out1, out2):
  779. Carla.host._set_peaks(pluginId, in1, in2, out1, out2)
  780. @pyqtSlot()
  781. def slot_handleExit(self):
  782. self.removeAll()
  783. if self.lo_server:
  784. self.lo_server.stop()
  785. self.lo_server = None
  786. self.ui.act_file_refresh.setEnabled(False)
  787. global lo_target, lo_targetName
  788. lo_target = None
  789. lo_targetName = ""
  790. self.lo_address = ""
  791. def saveSettings(self):
  792. settings = QSettings()
  793. settings.setValue("Geometry", self.saveGeometry())
  794. #settings.setValue("ShowToolbar", self.ui.toolBar.isVisible())
  795. def loadSettings(self):
  796. settings = QSettings()
  797. self.restoreGeometry(settings.value("Geometry", ""))
  798. #showToolbar = settings.value("ShowToolbar", True, type=bool)
  799. #self.ui.act_settings_show_toolbar.setChecked(showToolbar)
  800. #self.ui.toolBar.setVisible(showToolbar)
  801. def timerEvent(self, event):
  802. if event.timerId() == self.fIdleTimerFast:
  803. for pwidget in self.fPluginList:
  804. if pwidget is None:
  805. break
  806. pwidget.idleFast()
  807. elif event.timerId() == self.fIdleTimerSlow:
  808. for pwidget in self.fPluginList:
  809. if pwidget is None:
  810. break
  811. pwidget.idleSlow()
  812. QMainWindow.timerEvent(self, event)
  813. def closeEvent(self, event):
  814. self.saveSettings()
  815. global lo_target
  816. if lo_target and self.lo_server:
  817. lo_send(lo_target, "/unregister")
  818. QMainWindow.closeEvent(self, event)
  819. #--------------- main ------------------
  820. if __name__ == '__main__':
  821. # App initialization
  822. app = QApplication(sys.argv)
  823. app.setApplicationName("Carla-Control")
  824. app.setApplicationVersion(VERSION)
  825. app.setOrganizationName("Cadence")
  826. app.setWindowIcon(QIcon(":/scalable/carla-control.svg"))
  827. libPrefix = None
  828. for i in range(len(app.arguments())):
  829. if i == 0: continue
  830. argument = app.arguments()[i]
  831. if argument.startswith("--with-libprefix="):
  832. libPrefix = argument.replace("--with-libprefix=", "")
  833. if libPrefix is not None:
  834. libName = os.path.join(libPrefix, "lib", "carla", carla_libname)
  835. else:
  836. libName = carla_library_path
  837. # Load backend DLL, so it registers the theme
  838. libDLL = QLibrary()
  839. libDLL.setFileName(libName)
  840. try:
  841. libDLL.load()
  842. except:
  843. pass
  844. # Init backend (OSC bridge version)
  845. Carla.host = Host()
  846. # Create GUI
  847. Carla.gui = CarlaControlW()
  848. # Set-up custom signal handling
  849. setUpSignals()
  850. # Show GUI
  851. Carla.gui.show()
  852. # App-Loop
  853. ret = app.exec_()
  854. # Close backend DLL
  855. if libDLL.isLoaded():
  856. # Need to destroy app before theme
  857. del app
  858. libDLL.unload()
  859. sys.exit(ret)