Collection of tools useful for audio production
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.

1386 lines
58KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # ... TODO
  4. # Copyright (C) 2010-2018 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # 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 COPYING file
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. from random import randint
  20. import os
  21. if True:
  22. from PyQt5.QtCore import pyqtSlot, Qt, QTimer, QSettings
  23. from PyQt5.QtWidgets import QMainWindow, QTableWidgetItem, QWidget
  24. else:
  25. from PyQt4.QtCore import pyqtSlot, Qt, QTimer, QSettings
  26. from PyQt4.QtGui import QMainWindow, QTableWidgetItem, QWidget
  27. # ------------------------------------------------------------------------------------------------------------
  28. # Imports (Custom)
  29. import claudia_database as database
  30. import ui_claudia_launcher
  31. from shared import *
  32. # ------------------------------------------------------------------------------------------------------------
  33. # Imports (Carla)
  34. try:
  35. from carla_utils import *
  36. haveCarla = True
  37. except:
  38. haveCarla = False
  39. # ------------------------------------------------------------------------------------------------------------
  40. # Safe import getoutput
  41. if sys.version_info >= (3, 0):
  42. from subprocess import getoutput
  43. else:
  44. from commands import getoutput
  45. # ------------------------------------------------------------------------------------------------------------
  46. # Debug Mode
  47. SHOW_ALL = False
  48. # ------------------------------------------------------------------------------------------------------------
  49. # Tab Indexes
  50. iTabDAW = 0
  51. iTabHost = 1
  52. iTabInstrument = 2
  53. iTabBristol = 3
  54. iTabPlugin = 4
  55. iTabEffect = 5
  56. iTabTool = 6
  57. EXTRA_ICON_PATHS = [
  58. "/usr/share/icons",
  59. "/usr/share/pixmaps",
  60. "/usr/local/share/pixmaps"
  61. ]
  62. # ------------------------------------------------------------------------------------------------------------
  63. # XIcon class
  64. class XIcon(object):
  65. def __init__(self):
  66. object.__init__(self)
  67. def addIconPath(self, path):
  68. iconPaths = QIcon.themeSearchPaths()
  69. iconPaths.append(path)
  70. QIcon.setThemeSearchPaths(iconPaths)
  71. def getIcon(self, name):
  72. if os.path.exists(name):
  73. icon = QIcon(name)
  74. else:
  75. icon = QIcon.fromTheme(name)
  76. if icon.isNull():
  77. for iEXTRA_PATH in EXTRA_ICON_PATHS:
  78. if os.path.exists(os.path.join(iEXTRA_PATH, name + ".png")):
  79. icon = QIcon(os.path.join(iEXTRA_PATH, name + ".png"))
  80. break
  81. elif os.path.exists(os.path.join(iEXTRA_PATH, name + ".svg")):
  82. icon = QIcon(os.path.join(iEXTRA_PATH, name + ".svg"))
  83. break
  84. elif os.path.exists(os.path.join(iEXTRA_PATH, name + ".xpm")):
  85. icon = QIcon(os.path.join(iEXTRA_PATH, name + ".xpm"))
  86. break
  87. else:
  88. print("XIcon::getIcon(%s) - Failed to find icon" % name)
  89. return icon
  90. # ------------------------------------------------------------------------------------------------------------
  91. # Launcher object
  92. class ClaudiaLauncher(QWidget, ui_claudia_launcher.Ui_ClaudiaLauncherW):
  93. def __init__(self, parent):
  94. QWidget.__init__(self, parent)
  95. self.setupUi(self)
  96. self._parent = None
  97. self._settings = None
  98. self.m_ladish_only = False
  99. self.lib_path = LIB_PATH
  100. self.listDAW.setColumnWidth(0, 22)
  101. self.listDAW.setColumnWidth(1, 225)
  102. self.listDAW.setColumnWidth(2, 150)
  103. self.listHost.setColumnWidth(0, 22)
  104. self.listHost.setColumnWidth(1, 225)
  105. self.listHost.setColumnWidth(2, 100)
  106. self.listHost.setColumnWidth(3, 100)
  107. self.listInstrument.setColumnWidth(0, 22)
  108. self.listInstrument.setColumnWidth(1, 225)
  109. self.listInstrument.setColumnWidth(2, 150)
  110. self.listBristol.setColumnWidth(0, 22)
  111. self.listBristol.setColumnWidth(1, 150)
  112. self.listPlugin.setColumnWidth(0, 225)
  113. self.listPlugin.setColumnWidth(1, 175)
  114. self.listEffect.setColumnWidth(0, 22)
  115. self.listEffect.setColumnWidth(1, 225)
  116. self.listEffect.setColumnWidth(2, 150)
  117. self.listTool.setColumnWidth(0, 22)
  118. self.listTool.setColumnWidth(1, 225)
  119. self.listTool.setColumnWidth(2, 150)
  120. # For the custom icons
  121. self.ClaudiaIcons = XIcon()
  122. self.icon_yes = QIcon(self.getIcon("dialog-ok-apply"))
  123. self.icon_no = QIcon(self.getIcon("dialog-cancel"))
  124. self.m_lastThemeName = QIcon.themeName()
  125. # Copy our icons, so we can then set the fallback icon theme as the current theme
  126. iconPath = os.path.join(TMP, ".claudia-icons")
  127. if not os.path.exists(iconPath):
  128. os.mkdir(iconPath)
  129. syspath = sys.path[0]
  130. if os.path.exists(os.path.join(syspath, "..", "icons")):
  131. os.system("cp -r '%s' '%s'" % (os.path.join(syspath, "..", "icons", "claudia-hicolor"), iconPath))
  132. elif os.path.exists(os.path.join(syspath, "..", "data", "icons")):
  133. os.system("cp -r '%s' '%s'" % (os.path.join(syspath, "..", "data", "icons", "claudia-hicolor"), iconPath))
  134. os.system("sed -i 's/X-CURRENT-THEME-X/%s/' '%s'" % (self.m_lastThemeName, os.path.join(iconPath, "claudia-hicolor", "index.theme")))
  135. self.ClaudiaIcons.addIconPath(iconPath)
  136. QIcon.setThemeName("claudia-hicolor")
  137. self.clearInfo_DAW()
  138. self.clearInfo_Host()
  139. self.clearInfo_Intrument()
  140. self.clearInfo_Bristol()
  141. self.clearInfo_Plugin()
  142. self.clearInfo_Effect()
  143. self.clearInfo_Tool()
  144. self.refreshAll()
  145. self.tabWidget.currentChanged.connect(self.slot_checkSelectedTab)
  146. self.listDAW.currentCellChanged.connect(self.slot_checkSelectedDAW)
  147. self.listHost.currentCellChanged.connect(self.slot_checkSelectedHost)
  148. self.listInstrument.currentCellChanged.connect(self.slot_checkSelectedInstrument)
  149. self.listBristol.currentCellChanged.connect(self.slot_checkSelectedBristol)
  150. self.listPlugin.currentCellChanged.connect(self.slot_checkSelectedPlugin)
  151. self.listEffect.currentCellChanged.connect(self.slot_checkSelectedEffect)
  152. self.listTool.currentCellChanged.connect(self.slot_checkSelectedTool)
  153. self.listDAW.cellDoubleClicked.connect(self.slot_doubleClickedList)
  154. self.listHost.cellDoubleClicked.connect(self.slot_doubleClickedList)
  155. self.listInstrument.cellDoubleClicked.connect(self.slot_doubleClickedList)
  156. self.listBristol.cellDoubleClicked.connect(self.slot_doubleClickedList)
  157. self.listPlugin.cellDoubleClicked.connect(self.slot_doubleClickedList)
  158. self.listEffect.cellDoubleClicked.connect(self.slot_doubleClickedList)
  159. self.listTool.cellDoubleClicked.connect(self.slot_doubleClickedList)
  160. def getSelectedAppAndBinary(self):
  161. tabIndex = self.tabWidget.currentIndex()
  162. if tabIndex == iTabDAW:
  163. item = self.listDAW.item(self.listDAW.currentRow(), 0).data(Qt.UserRole)
  164. return (item[database.iDAW_AppName], item[database.iDAW_Binary])
  165. if tabIndex == iTabHost:
  166. item = self.listHost.item(self.listHost.currentRow(), 0).data(Qt.UserRole)
  167. return (item[database.iHost_AppName], item[database.iHost_Binary])
  168. if tabIndex == iTabInstrument:
  169. item = self.listInstrument.item(self.listInstrument.currentRow(), 0).data(Qt.UserRole)
  170. return (item[database.iInstrument_AppName], item[database.iInstrument_Binary])
  171. if tabIndex == iTabBristol:
  172. item = self.listBristol.item(self.listBristol.currentRow(), 0).data(Qt.UserRole)
  173. return (item[database.iBristol_AppName], "startBristol -audio jack -midi jack -%s" % item[database.iBristol_ShortName])
  174. if tabIndex == iTabPlugin:
  175. plugin = self.listPlugin.item(self.listPlugin.currentRow(), 0).data(Qt.UserRole)
  176. return (plugin["name"], "carla-single lv2 %s" % plugin["label"])
  177. if tabIndex == iTabEffect:
  178. item = self.listEffect.item(self.listEffect.currentRow(), 0).data(Qt.UserRole)
  179. return (item[database.iEffect_AppName], item[database.iEffect_Binary])
  180. if tabIndex == iTabTool:
  181. item = self.listTool.item(self.listTool.currentRow(), 0).data(Qt.UserRole)
  182. return (item[database.iTool_AppName], item[database.iTool_Binary])
  183. return ("", "")
  184. def startApp(self):
  185. app, binary = self.getSelectedAppAndBinary()
  186. if not (app and binary):
  187. return
  188. os.system("cd '%s' && %s &" % (self.callback_getProjectFolder(), binary))
  189. def addAppToLADISH(self):
  190. app, binary = self.getSelectedAppAndBinary()
  191. if not (app and binary):
  192. return
  193. if binary.startswith("startBristol") or binary.startswith("carla-single"):
  194. self.createAppTemplate(app, binary)
  195. elif binary in ("ardour",
  196. "ardour3",
  197. "hydrogen",
  198. "jacker",
  199. "lmms",
  200. "muse",
  201. "non-sequencer",
  202. "non-timeline",
  203. "qtractor",
  204. "rosegarden",
  205. "seq24",
  206. "calfjackhost",
  207. "carla",
  208. "jack-rack",
  209. "qsampler",
  210. "jack-mixer"):
  211. self.createAppTemplate(app, binary)
  212. else:
  213. appBus = self.callback_getAppBus()
  214. appBus.RunCustom2(False, binary, app, "0")
  215. def createAppTemplate(self, app, binary):
  216. rand_check = randint(1, 99999)
  217. proj_bpm = str(self.callback_getBPM())
  218. proj_srate = str(self.callback_getSampleRate())
  219. proj_folder = self.callback_getProjectFolder()
  220. tmplte_dir = None
  221. tmplte_file = None
  222. tmplte_cmd = ""
  223. tmplte_lvl = "0"
  224. syspath = sys.path[0]
  225. if os.path.exists(os.path.join(syspath, "..", "templates")):
  226. tmplte_dir = os.path.join(syspath, "..", "templates")
  227. elif os.path.exists(os.path.join(syspath, "..", "data", "templates")):
  228. tmplte_dir = os.path.join(syspath, "..", "data", "templates")
  229. else:
  230. app = None
  231. tmplte_cmd = binary
  232. print("ClaudiaLauncher::createAppTemplate() - Failed to find template dir")
  233. return False
  234. if not os.path.exists(proj_folder):
  235. os.mkdir(proj_folder)
  236. if binary.startswith("startBristol"):
  237. module = binary.replace("startBristol -audio jack -midi jack -", "")
  238. tmplte_folder = os.path.join(proj_folder, "bristol_%s_%i" % (module, rand_check))
  239. os.mkdir(tmplte_folder)
  240. if self.callback_isLadishRoom():
  241. tmplte_folder = os.path.basename(tmplte_folder)
  242. tmplte_cmd = binary
  243. tmplte_cmd += " -emulate %s" % module
  244. tmplte_cmd += " -cache '%s'" % tmplte_folder
  245. tmplte_cmd += " -memdump '%s'" % tmplte_folder
  246. tmplte_cmd += " -import '%s'" % os.path.join(tmplte_folder, "memory")
  247. tmplte_cmd += " -exec"
  248. tmplte_lvl = "1"
  249. elif binary.startswith("carla-single"):
  250. tmplte_cmd = binary + " " + proj_folder
  251. tmplte_lvl = "1"
  252. elif binary == "ardour":
  253. tmplte_folder = os.path.join(proj_folder, "Ardour2_%i" % rand_check)
  254. tmplte_file = os.path.join(tmplte_folder, "Ardour2_%i.ardour" % rand_check)
  255. os.mkdir(tmplte_folder)
  256. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Ardour2", "Ardour2.ardour"), tmplte_file))
  257. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Ardour2", "instant.xml"), tmplte_folder))
  258. os.mkdir(os.path.join(tmplte_folder, "analysis"))
  259. os.mkdir(os.path.join(tmplte_folder, "dead_sounds"))
  260. os.mkdir(os.path.join(tmplte_folder, "export"))
  261. os.mkdir(os.path.join(tmplte_folder, "interchange"))
  262. os.mkdir(os.path.join(tmplte_folder, "interchange", "Ardour"))
  263. os.mkdir(os.path.join(tmplte_folder, "interchange", "Ardour", "audiofiles"))
  264. os.mkdir(os.path.join(tmplte_folder, "peaks"))
  265. tmplte_cmd = binary
  266. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_folder) if self.callback_isLadishRoom() else tmplte_folder)
  267. elif binary == "ardour3":
  268. projName = "Ardour3_%i" % rand_check
  269. tmplte_folder = os.path.join(proj_folder, projName)
  270. tmplte_file = os.path.join(tmplte_folder, "%s.ardour" % projName)
  271. os.mkdir(tmplte_folder)
  272. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Ardour3", "Ardour3.ardour"), tmplte_file))
  273. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Ardour3", "instant.xml"), tmplte_folder))
  274. os.mkdir(os.path.join(tmplte_folder, "analysis"))
  275. os.mkdir(os.path.join(tmplte_folder, "dead"))
  276. os.mkdir(os.path.join(tmplte_folder, "export"))
  277. os.mkdir(os.path.join(tmplte_folder, "externals"))
  278. os.mkdir(os.path.join(tmplte_folder, "interchange"))
  279. os.mkdir(os.path.join(tmplte_folder, "interchange", projName))
  280. os.mkdir(os.path.join(tmplte_folder, "interchange", projName, "audiofiles"))
  281. os.mkdir(os.path.join(tmplte_folder, "interchange", projName, "midifiles"))
  282. os.mkdir(os.path.join(tmplte_folder, "peaks"))
  283. os.mkdir(os.path.join(tmplte_folder, "plugins"))
  284. tmplte_cmd = binary
  285. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_folder) if self.callback_isLadishRoom() else tmplte_folder)
  286. if self.callback_isLadishRoom():
  287. tmplte_lvl = "jacksession"
  288. elif binary == "hydrogen":
  289. tmplte_file = os.path.join(proj_folder, "Hydrogen_%i.h2song" % rand_check)
  290. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Hydrogen.h2song"), tmplte_file))
  291. tmplte_cmd = binary
  292. tmplte_cmd += " -s '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  293. if self.callback_isLadishRoom():
  294. tmplte_lvl = "jacksession"
  295. else:
  296. tmplte_lvl = "1"
  297. elif binary == "jacker":
  298. tmplte_file = os.path.join(proj_folder, "Jacker_%i.jsong" % rand_check)
  299. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Jacker.jsong"), tmplte_file))
  300. tmplte_cmd = binary
  301. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  302. if database.USING_KXSTUDIO:
  303. tmplte_lvl = "1"
  304. # No decimal bpm support
  305. proj_bpm = proj_bpm.split(".")[0]
  306. elif binary == "lmms":
  307. tmplte_file = os.path.join(proj_folder, "LMMS_%i.mmp" % rand_check)
  308. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "LMMS.mmp"), tmplte_file))
  309. tmplte_cmd = binary
  310. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  311. # No decimal bpm support
  312. proj_bpm = proj_bpm.split(".",1)[0]
  313. elif binary == "muse":
  314. tmplte_file = os.path.join(proj_folder, "MusE_%i.med" % rand_check)
  315. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "MusE.med"), tmplte_file))
  316. tmplte_cmd = binary
  317. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  318. elif binary == "non-sequencer":
  319. tmplte_file_r = os.path.join(proj_folder, "Non-Sequencer_%i.non" % rand_check)
  320. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Non-Sequencer.non"), tmplte_file_r))
  321. tmplte_cmd = binary
  322. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file_r) if self.callback_isLadishRoom() else tmplte_file_r)
  323. elif binary == "non-timeline":
  324. tmplte_folder = os.path.join(proj_folder, "Non-Timeline_%i" % rand_check)
  325. os.mkdir(tmplte_folder)
  326. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Non-Timeline", "history"), tmplte_folder))
  327. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Non-Timeline", "info"), tmplte_folder))
  328. os.mkdir(os.path.join(tmplte_folder, "sources"))
  329. os.system('sed -i "s/X_SR_X-CLAUDIA-X_SR_X/%s/" "%s"' % (proj_srate, os.path.join(tmplte_folder, "info")))
  330. os.system('sed -i "s/X_BPM_X-CLAUDIA-X_BPM_X/%s/" "%s"' % (proj_bpm, os.path.join(tmplte_folder, "history")))
  331. tmplte_cmd = binary
  332. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_folder) if self.callback_isLadishRoom() else tmplte_folder)
  333. elif binary == "qtractor":
  334. tmplte_file = os.path.join(proj_folder, "Qtractor_%i.qtr" % rand_check)
  335. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Qtractor.qtr"), tmplte_file))
  336. tmplte_cmd = binary
  337. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  338. tmplte_lvl = "1"
  339. elif binary == "rosegarden":
  340. tmplte_file = os.path.join(proj_folder, "Rosegarden_%i.rg" % rand_check)
  341. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Rosegarden.rg"), tmplte_file))
  342. tmplte_cmd = binary
  343. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  344. tmplte_lvl = "1"
  345. elif binary == "seq24":
  346. tmplte_file_r = os.path.join(proj_folder, "Seq24_%i.midi" % rand_check)
  347. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Seq24.midi"), tmplte_file_r))
  348. tmplte_cmd = binary
  349. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file_r) if self.callback_isLadishRoom() else tmplte_file_r)
  350. tmplte_lvl = "1"
  351. elif binary == "calfjackhost":
  352. tmplte_file = os.path.join(proj_folder, "CalfJackHost_%i" % rand_check)
  353. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "CalfJackHost"), tmplte_file))
  354. tmplte_cmd = binary
  355. tmplte_cmd += " --load '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  356. tmplte_lvl = "1"
  357. elif binary == "carla":
  358. tmplte_file = os.path.join(proj_folder, "Carla_%i.carxp" % rand_check)
  359. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Carla.carxp"), tmplte_file))
  360. tmplte_cmd = binary
  361. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  362. tmplte_lvl = "1"
  363. elif binary == "jack-rack":
  364. tmplte_file = os.path.join(proj_folder, "Jack-Rack_%i.xml" % rand_check)
  365. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Jack-Rack.xml"), tmplte_file))
  366. tmplte_cmd = binary
  367. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  368. elif binary == "qsampler":
  369. tmplte_file = os.path.join(proj_folder, "Qsampler_%i.lscp" % rand_check)
  370. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Qsampler.lscp"), tmplte_file))
  371. tmplte_cmd = binary
  372. tmplte_cmd += " '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  373. elif binary == "jack-mixer":
  374. tmplte_file = os.path.join(proj_folder, "Jack-Mixer_%i.xml" % rand_check)
  375. os.system("cp '%s' '%s'" % (os.path.join(tmplte_dir, "Jack-Mixer.xml"), tmplte_file))
  376. tmplte_cmd = binary
  377. tmplte_cmd += " -c '%s'" % (os.path.basename(tmplte_file) if self.callback_isLadishRoom() else tmplte_file)
  378. else:
  379. print("ClaudiaLauncher::createAppTemplate(%s) - Failed to parse app name" % app)
  380. return False
  381. if tmplte_file is not None:
  382. os.system('sed -i "s|X_SR_X-CLAUDIA-X_SR_X|%s|" "%s"' % (proj_srate, tmplte_file))
  383. os.system('sed -i "s|X_BPM_X-CLAUDIA-X_BPM_X|%s|" "%s"' % (proj_bpm, tmplte_file))
  384. os.system('sed -i "s|X_FOLDER_X-CLAUDIA-X_FOLDER_X|%s|" "%s"' % (proj_folder.replace("|", "\|").replace("$", "\$"), tmplte_file))
  385. appBus = self.callback_getAppBus()
  386. appBus.RunCustom2(False, tmplte_cmd, app, tmplte_lvl)
  387. return True
  388. def parentR(self):
  389. return self._parent
  390. def settings(self):
  391. return self._settings
  392. def getIcon(self, icon):
  393. return self.ClaudiaIcons.getIcon(icon)
  394. def getIconForYesNo(self, yesno):
  395. return self.icon_yes if yesno else self.icon_no
  396. def setCallbackApp(self, parent, settings, ladish_only):
  397. self._parent = parent
  398. self._settings = settings
  399. self.m_ladish_only = ladish_only
  400. def clearInfo_DAW(self):
  401. self.ico_app_daw.setPixmap(self.getIcon("start-here").pixmap(48, 48))
  402. self.label_name_daw.setText("App Name")
  403. self.ico_ladspa_daw.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  404. self.ico_dssi_daw.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  405. self.ico_lv2_daw.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  406. self.ico_vst_daw.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  407. self.label_vst_mode_daw.setText("")
  408. self.ico_jack_transport_daw.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  409. self.label_midi_mode_daw.setText("---")
  410. self.label_session_level_daw.setText(database.LEVEL_0)
  411. self.frame_DAW.setEnabled(False)
  412. self.showDoc_DAW("", "")
  413. def clearInfo_Host(self):
  414. self.ico_app_host.setPixmap(self.getIcon("start-here").pixmap(48, 48))
  415. self.label_name_host.setText("App Name")
  416. self.ico_ladspa_host.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  417. self.ico_dssi_host.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  418. self.ico_lv2_host.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  419. self.ico_vst_host.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  420. self.label_vst_mode_host.setText("")
  421. self.label_midi_mode_host.setText("---")
  422. self.label_session_level_host.setText(database.LEVEL_0)
  423. self.frame_Host.setEnabled(False)
  424. self.showDoc_Host("", "")
  425. def clearInfo_Intrument(self):
  426. self.ico_app_ins.setPixmap(self.getIcon("start-here").pixmap(48, 48))
  427. self.label_name_ins.setText("App Name")
  428. self.ico_builtin_fx_ins.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  429. self.ico_audio_input_ins.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  430. self.label_midi_mode_ins.setText("---")
  431. self.label_session_level_ins.setText(database.LEVEL_0)
  432. self.frame_Instrument.setEnabled(False)
  433. self.showDoc_Instrument("", "")
  434. def clearInfo_Bristol(self):
  435. self.ico_app_bristol.setPixmap(self.getIcon("start-here").pixmap(48, 48))
  436. self.label_name_bristol.setText("App Name")
  437. self.ico_builtin_fx_bristol.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  438. self.ico_audio_input_bristol.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  439. self.label_midi_mode_bristol.setText("---")
  440. self.label_session_level_bristol.setText(database.LEVEL_0)
  441. self.frame_Bristol.setEnabled(False)
  442. self.showDoc_Bristol("", "")
  443. def clearInfo_Plugin(self):
  444. self.ico_app_plugin.setPixmap(self.getIcon("lv2").pixmap(48, 48))
  445. self.label_name_plugin.setText("Plugin Name")
  446. self.label_plugin_audio_ins.setText("0")
  447. self.label_plugin_audio_outs.setText("0")
  448. self.label_plugin_midi_ins.setText("0")
  449. self.label_plugin_midi_outs.setText("0")
  450. self.label_plugin_parameter_ins.setText("0")
  451. self.label_plugin_parameter_outs.setText("0")
  452. self.frame_Plugin.setEnabled(False)
  453. self.showDoc_Plugin("", "")
  454. def clearInfo_Effect(self):
  455. self.ico_app_effect.setPixmap(self.getIcon("start-here").pixmap(48, 48))
  456. self.label_name_effect.setText("App Name")
  457. self.ico_stereo_effect.setPixmap(self.getIconForYesNo(False).pixmap(16, 16))
  458. self.label_midi_mode_effect.setText("---")
  459. self.label_session_level_effect.setText(database.LEVEL_0)
  460. self.frame_Effect.setEnabled(False)
  461. self.showDoc_Effect("", "")
  462. def clearInfo_Tool(self):
  463. self.ico_app_tool.setPixmap(self.getIcon("start-here").pixmap(48, 48))
  464. self.label_name_tool.setText("App Name")
  465. self.label_midi_mode_tool.setText("---")
  466. self.label_session_level_tool.setText(database.LEVEL_0)
  467. self.frame_Tool.setEnabled(False)
  468. self.showDoc_Tool("", "")
  469. def showDoc_DAW(self, doc, web):
  470. self.url_documentation_daw.setVisible(bool(doc))
  471. self.url_website_daw.setVisible(bool(web))
  472. self.label_no_help_daw.setVisible(not(doc or web))
  473. if doc: self.setDocUrl(self.url_documentation_daw, doc)
  474. if web: self.setWebUrl(self.url_website_daw, web)
  475. def showDoc_Host(self, doc, web):
  476. self.url_documentation_host.setVisible(bool(doc))
  477. self.url_website_host.setVisible(bool(web))
  478. self.label_no_help_host.setVisible(not(doc or web))
  479. if doc: self.setDocUrl(self.url_documentation_host, doc)
  480. if web: self.setWebUrl(self.url_website_host, web)
  481. def showDoc_Instrument(self, doc, web):
  482. self.url_documentation_ins.setVisible(bool(doc))
  483. self.url_website_ins.setVisible(bool(web))
  484. self.label_no_help_ins.setVisible(not(doc or web))
  485. if doc: self.setDocUrl(self.url_documentation_ins, doc)
  486. if web: self.setWebUrl(self.url_website_ins, web)
  487. def showDoc_Bristol(self, doc, web):
  488. self.url_documentation_bristol.setVisible(bool(doc))
  489. self.url_website_bristol.setVisible(bool(web))
  490. self.label_no_help_bristol.setVisible(not(doc or web))
  491. if doc: self.setDocUrl(self.url_documentation_bristol, doc)
  492. if web: self.setWebUrl(self.url_website_bristol, web)
  493. def showDoc_Plugin(self, doc, web):
  494. self.url_documentation_plugin.setVisible(bool(doc))
  495. self.url_website_plugin.setVisible(bool(web))
  496. self.label_no_help_plugin.setVisible(not(doc or web))
  497. if doc: self.setDocUrl(self.url_documentation_plugin, doc)
  498. if web: self.setWebUrl(self.url_website_plugin, web)
  499. def showDoc_Effect(self, doc, web):
  500. self.url_documentation_effect.setVisible(bool(doc))
  501. self.url_website_effect.setVisible(bool(web))
  502. self.label_no_help_effect.setVisible(not(doc or web))
  503. if doc: self.setDocUrl(self.url_documentation_effect, doc)
  504. if web: self.setWebUrl(self.url_website_effect, web)
  505. def showDoc_Tool(self, doc, web):
  506. self.url_documentation_tool.setVisible(bool(doc))
  507. self.url_website_tool.setVisible(bool(web))
  508. self.label_no_help_tool.setVisible(not(doc or web))
  509. if doc: self.setDocUrl(self.url_documentation_tool, doc)
  510. if web: self.setWebUrl(self.url_website_tool, web)
  511. def setDocUrl(self, item, link):
  512. item.setText(self.tr("<a href='%s'>Documentation</a>" % link))
  513. def setWebUrl(self, item, link):
  514. item.setText(self.tr("<a href='%s'>WebSite</a>" % link))
  515. def clearAll(self):
  516. self.listDAW.clearContents()
  517. self.listHost.clearContents()
  518. self.listInstrument.clearContents()
  519. self.listBristol.clearContents()
  520. self.listPlugin.clearContents()
  521. self.listEffect.clearContents()
  522. self.listTool.clearContents()
  523. for x in range(self.listDAW.rowCount()):
  524. self.listDAW.removeRow(0)
  525. for x in range(self.listHost.rowCount()):
  526. self.listHost.removeRow(0)
  527. for x in range(self.listInstrument.rowCount()):
  528. self.listInstrument.removeRow(0)
  529. for x in range(self.listBristol.rowCount()):
  530. self.listBristol.removeRow(0)
  531. for x in range(self.listPlugin.rowCount()):
  532. self.listPlugin.removeRow(0)
  533. for x in range(self.listEffect.rowCount()):
  534. self.listEffect.removeRow(0)
  535. for x in range(self.listTool.rowCount()):
  536. self.listTool.removeRow(0)
  537. def refreshAll(self):
  538. self.clearAll()
  539. pkglist = []
  540. if not SHOW_ALL:
  541. if os.path.exists("/usr/bin/yaourt"):
  542. pkg_out = getoutput("env LANG=C LC_ALL=C /usr/bin/yaourt -Qsq 2>/dev/null").split("\n")
  543. for package in pkg_out:
  544. pkglist.append(package)
  545. elif os.path.exists("/usr/bin/pacman"):
  546. pkg_out = getoutput("env LANG=C LC_ALL=C /usr/bin/pacman -Qsq 2>/dev/null").split("\n")
  547. for package in pkg_out:
  548. pkglist.append(package)
  549. elif os.path.exists("/usr/bin/dpkg"):
  550. pkg_out = getoutput("env LANG=C LC_ALL=C /usr/bin/dpkg --get-selections 2>/dev/null").split("\n")
  551. for pkg_info in pkg_out:
  552. package, installed = pkg_info.rsplit("\t", 1)
  553. if installed == "install":
  554. pkglist.append(package.strip())
  555. elif os.path.exists("/bin/rpm"):
  556. pkg_out = getoutput("env LANG=C /bin/rpm -qa --qf \"%{NAME}\n\" 2>/dev/null").split("\n")
  557. for package in pkg_out:
  558. pkglist.append(package)
  559. if not "bristol" in pkglist:
  560. self.tabWidget.setTabEnabled(iTabBristol, False)
  561. if not "carla-git" in pkglist:
  562. self.tabWidget.setTabEnabled(iTabPlugin, False)
  563. last_pos = 0
  564. for item in database.list_DAW:
  565. Package, AppName, Type, Binary, Icon, Save, Level, Features, Docs = item
  566. if SHOW_ALL or Package in pkglist:
  567. w_icon = QTableWidgetItem("")
  568. w_icon.setData(Qt.UserRole, item)
  569. w_icon.setIcon(QIcon(self.getIcon(Icon)))
  570. w_name = QTableWidgetItem(AppName)
  571. w_type = QTableWidgetItem(Type)
  572. w_save = QTableWidgetItem(Save)
  573. self.listDAW.insertRow(last_pos)
  574. self.listDAW.setItem(last_pos, 0, w_icon)
  575. self.listDAW.setItem(last_pos, 1, w_name)
  576. self.listDAW.setItem(last_pos, 2, w_type)
  577. self.listDAW.setItem(last_pos, 3, w_save)
  578. last_pos += 1
  579. last_pos = 0
  580. for item in database.list_Host:
  581. Package, AppName, Instruments, Effects, Binary, Icon, Save, Level, Features, Docs = item
  582. if SHOW_ALL or Package in pkglist:
  583. w_icon = QTableWidgetItem("")
  584. w_icon.setData(Qt.UserRole, item)
  585. w_icon.setIcon(QIcon(self.getIcon(Icon)))
  586. w_name = QTableWidgetItem(AppName)
  587. w_h_in = QTableWidgetItem(Instruments)
  588. w_h_ef = QTableWidgetItem(Effects)
  589. w_save = QTableWidgetItem(Save)
  590. self.listHost.insertRow(last_pos)
  591. self.listHost.setItem(last_pos, 0, w_icon)
  592. self.listHost.setItem(last_pos, 1, w_name)
  593. self.listHost.setItem(last_pos, 2, w_h_in)
  594. self.listHost.setItem(last_pos, 3, w_h_ef)
  595. self.listHost.setItem(last_pos, 4, w_save)
  596. last_pos += 1
  597. last_pos = 0
  598. for item in database.list_Instrument:
  599. Package, AppName, Type, Binary, Icon, Save, Level, Features, Docs = item
  600. if SHOW_ALL or Package in pkglist:
  601. w_icon = QTableWidgetItem("")
  602. w_icon.setData(Qt.UserRole, item)
  603. w_icon.setIcon(QIcon(self.getIcon(Icon)))
  604. w_name = QTableWidgetItem(AppName)
  605. w_type = QTableWidgetItem(Type)
  606. w_save = QTableWidgetItem(Save)
  607. self.listInstrument.insertRow(last_pos)
  608. self.listInstrument.setItem(last_pos, 0, w_icon)
  609. self.listInstrument.setItem(last_pos, 1, w_name)
  610. self.listInstrument.setItem(last_pos, 2, w_type)
  611. self.listInstrument.setItem(last_pos, 3, w_save)
  612. last_pos += 1
  613. last_pos = 0
  614. for item in database.list_Bristol:
  615. Package, FullName, Type, ShortName, Icon, Save, Level, Features, Docs = item
  616. if SHOW_ALL or Package in pkglist:
  617. w_icon = QTableWidgetItem("")
  618. w_icon.setData(Qt.UserRole, item)
  619. w_icon.setIcon(QIcon(self.getIcon(Icon)))
  620. w_fullname = QTableWidgetItem(FullName)
  621. w_shortname = QTableWidgetItem(ShortName)
  622. self.listBristol.insertRow(last_pos)
  623. self.listBristol.setItem(last_pos, 0, w_icon)
  624. self.listBristol.setItem(last_pos, 1, w_shortname)
  625. self.listBristol.setItem(last_pos, 2, w_fullname)
  626. last_pos += 1
  627. last_pos = 0
  628. for item in database.list_Effect:
  629. Package, AppName, Type, Binary, Icon, Save, Level, Features, Docs = item
  630. if SHOW_ALL or Package in pkglist:
  631. w_icon = QTableWidgetItem("")
  632. w_icon.setData(Qt.UserRole, item)
  633. w_icon.setIcon(QIcon(self.getIcon(Icon)))
  634. w_name = QTableWidgetItem(AppName)
  635. w_type = QTableWidgetItem(Type)
  636. w_save = QTableWidgetItem(Save)
  637. self.listEffect.insertRow(last_pos)
  638. self.listEffect.setItem(last_pos, 0, w_icon)
  639. self.listEffect.setItem(last_pos, 1, w_name)
  640. self.listEffect.setItem(last_pos, 2, w_type)
  641. self.listEffect.setItem(last_pos, 3, w_save)
  642. last_pos += 1
  643. last_pos = 0
  644. for item in database.list_Tool:
  645. Package, AppName, Type, Binary, Icon, Save, Level, Features, Docs = item
  646. if SHOW_ALL or Package in pkglist:
  647. w_icon = QTableWidgetItem("")
  648. w_icon.setData(Qt.UserRole, item)
  649. w_icon.setIcon(QIcon(self.getIcon(Icon)))
  650. w_name = QTableWidgetItem(AppName)
  651. w_type = QTableWidgetItem(Type)
  652. w_save = QTableWidgetItem(Save)
  653. self.listTool.insertRow(last_pos)
  654. self.listTool.setItem(last_pos, 0, w_icon)
  655. self.listTool.setItem(last_pos, 1, w_name)
  656. self.listTool.setItem(last_pos, 2, w_type)
  657. self.listTool.setItem(last_pos, 3, w_save)
  658. last_pos += 1
  659. if haveCarla and os.path.exists("/usr/{}/carla/libcarla_utils.so".format(self.lib_path)):
  660. utils = CarlaUtils("/usr/{}/carla/libcarla_utils.so".format(self.lib_path))
  661. last_pos = 0
  662. for i in range(utils.get_cached_plugin_count(PLUGIN_LV2,
  663. os.getenv("LV2_PATH",
  664. "~/.lv2:"\
  665. "/usr/{lib_path}/lv2:"\
  666. "/usr/local/{lib_path}/lv2".format(lib_path=self.lib_path)))):
  667. plugin = utils.get_cached_plugin_info(PLUGIN_LV2, i)
  668. if (plugin["hints"] & PLUGIN_HAS_CUSTOM_UI) == 0:
  669. continue
  670. catgtext = ""
  671. if plugin["category"] == PLUGIN_CATEGORY_SYNTH:
  672. catgtext = "Synth"
  673. elif plugin["category"] == PLUGIN_CATEGORY_DELAY:
  674. catgtext = "Delay"
  675. elif plugin["category"] == PLUGIN_CATEGORY_EQ:
  676. catgtext = "Equalizer"
  677. elif plugin["category"] == PLUGIN_CATEGORY_FILTER:
  678. catgtext = "Filter"
  679. elif plugin["category"] == PLUGIN_CATEGORY_DISTORTION:
  680. catgtext = "Distortion"
  681. elif plugin["category"] == PLUGIN_CATEGORY_DYNAMICS:
  682. catgtext = "Dynamics"
  683. elif plugin["category"] == PLUGIN_CATEGORY_MODULATOR:
  684. catgtext = "Modulator"
  685. elif plugin["category"] == PLUGIN_CATEGORY_UTILITY:
  686. catgtext = "Utility"
  687. elif plugin["category"] == PLUGIN_CATEGORY_OTHER:
  688. catgtext = "Other"
  689. if not plugin["category"]:
  690. if plugin["hints"] & PLUGIN_IS_SYNTH:
  691. catgtext = "Synth"
  692. else:
  693. catgtext = "FX"
  694. w_name = QTableWidgetItem(plugin["name"])
  695. w_auth = QTableWidgetItem(plugin["maker"])
  696. w_catg = QTableWidgetItem(catgtext)
  697. w_name.setData(Qt.UserRole, plugin)
  698. self.listPlugin.insertRow(last_pos)
  699. self.listPlugin.setItem(last_pos, 0, w_name)
  700. self.listPlugin.setItem(last_pos, 1, w_auth)
  701. self.listPlugin.setItem(last_pos, 2, w_catg)
  702. last_pos += 1
  703. self.listDAW.setCurrentCell(-1, -1)
  704. self.listHost.setCurrentCell(-1, -1)
  705. self.listInstrument.setCurrentCell(-1, -1)
  706. self.listBristol.setCurrentCell(-1, -1)
  707. self.listPlugin.setCurrentCell(-1, -1)
  708. self.listEffect.setCurrentCell(-1, -1)
  709. self.listTool.setCurrentCell(-1, -1)
  710. self.listDAW.sortByColumn(1, Qt.AscendingOrder)
  711. self.listHost.sortByColumn(1, Qt.AscendingOrder)
  712. self.listInstrument.sortByColumn(1, Qt.AscendingOrder)
  713. self.listBristol.sortByColumn(2, Qt.AscendingOrder)
  714. self.listPlugin.sortByColumn(0, Qt.AscendingOrder)
  715. self.listEffect.sortByColumn(1, Qt.AscendingOrder)
  716. self.listTool.sortByColumn(1, Qt.AscendingOrder)
  717. @pyqtSlot(int)
  718. def slot_checkSelectedTab(self, tabIndex):
  719. if tabIndex == iTabDAW:
  720. test_selected = (len(self.listDAW.selectedItems()) > 0)
  721. elif tabIndex == iTabHost:
  722. test_selected = (len(self.listHost.selectedItems()) > 0)
  723. elif tabIndex == iTabInstrument:
  724. test_selected = (len(self.listInstrument.selectedItems()) > 0)
  725. elif tabIndex == iTabBristol:
  726. test_selected = (len(self.listBristol.selectedItems()) > 0)
  727. elif tabIndex == iTabPlugin:
  728. test_selected = (len(self.listPlugin.selectedItems()) > 0)
  729. elif tabIndex == iTabEffect:
  730. test_selected = (len(self.listEffect.selectedItems()) > 0)
  731. elif tabIndex == iTabTool:
  732. test_selected = (len(self.listTool.selectedItems()) > 0)
  733. else:
  734. test_selected = False
  735. self.callback_checkGUI(test_selected)
  736. @pyqtSlot(int)
  737. def slot_checkSelectedDAW(self, row):
  738. if row >= 0:
  739. item = self.listDAW.item(row, 0).data(Qt.UserRole)
  740. Package, AppName, Type, Binary, Icon, Save, Level, Features, Docs = item
  741. self.frame_DAW.setEnabled(True)
  742. self.ico_app_daw.setPixmap(QIcon(self.getIcon(Icon)).pixmap(48, 48))
  743. self.ico_ladspa_daw.setPixmap(QIcon(self.getIconForYesNo(Features[0])).pixmap(16, 16))
  744. self.ico_dssi_daw.setPixmap(QIcon(self.getIconForYesNo(Features[1])).pixmap(16, 16))
  745. self.ico_lv2_daw.setPixmap(QIcon(self.getIconForYesNo(Features[2])).pixmap(16, 16))
  746. self.ico_vst_daw.setPixmap(QIcon(self.getIconForYesNo(Features[3])).pixmap(16, 16))
  747. self.ico_jack_transport_daw.setPixmap(QIcon(self.getIconForYesNo(Features[5])).pixmap(16, 16))
  748. self.label_name_daw.setText(AppName)
  749. self.label_vst_mode_daw.setText(Features[4])
  750. self.ico_midi_mode_daw.setPixmap(QIcon(self.getIconForYesNo(Features[6])).pixmap(16, 16))
  751. self.label_midi_mode_daw.setText(Features[7])
  752. self.label_session_level_daw.setText(Level)
  753. Docs0 = Docs[0] if (os.path.exists(Docs[0].replace("file://", ""))) else ""
  754. self.showDoc_DAW(Docs0, Docs[1])
  755. else:
  756. self.clearInfo_DAW()
  757. self.callback_checkGUI(row >= 0)
  758. @pyqtSlot(int)
  759. def slot_checkSelectedHost(self, row):
  760. if row >= 0:
  761. item = self.listHost.item(row, 0).data(Qt.UserRole)
  762. Package, AppName, Instruments, Effects, Binary, Icon, Save, Level, Features, Docs = item
  763. self.frame_Host.setEnabled(True)
  764. self.ico_app_host.setPixmap(self.getIcon(Icon).pixmap(48, 48))
  765. self.ico_internal_host.setPixmap(self.getIconForYesNo(Features[0]).pixmap(16, 16))
  766. self.ico_ladspa_host.setPixmap(self.getIconForYesNo(Features[1]).pixmap(16, 16))
  767. self.ico_dssi_host.setPixmap(self.getIconForYesNo(Features[2]).pixmap(16, 16))
  768. self.ico_lv2_host.setPixmap(self.getIconForYesNo(Features[3]).pixmap(16, 16))
  769. self.ico_vst_host.setPixmap(self.getIconForYesNo(Features[4]).pixmap(16, 16))
  770. self.label_name_host.setText(AppName)
  771. self.label_vst_mode_host.setText(Features[5])
  772. self.label_midi_mode_host.setText(Features[6])
  773. self.label_session_level_host.setText(str(Level))
  774. Docs0 = Docs[0] if (os.path.exists(Docs[0].replace("file://", ""))) else ""
  775. self.showDoc_Host(Docs0, Docs[1])
  776. else:
  777. self.clearInfo_DAW()
  778. self.callback_checkGUI(row >= 0)
  779. @pyqtSlot(int)
  780. def slot_checkSelectedInstrument(self, row):
  781. if row >= 0:
  782. item = self.listInstrument.item(row, 0).data(Qt.UserRole)
  783. Package, AppName, Type, Binary, Icon, Save, Level, Features, Docs = item
  784. self.frame_Instrument.setEnabled(True)
  785. self.ico_app_ins.setPixmap(self.getIcon(Icon).pixmap(48, 48))
  786. self.ico_builtin_fx_ins.setPixmap(self.getIconForYesNo(Features[0]).pixmap(16, 16))
  787. self.ico_audio_input_ins.setPixmap(self.getIconForYesNo(Features[1]).pixmap(16, 16))
  788. self.label_name_ins.setText(AppName)
  789. self.label_midi_mode_ins.setText(Features[2])
  790. self.label_session_level_ins.setText(str(Level))
  791. Docs0 = Docs[0] if (os.path.exists(Docs[0].replace("file://", ""))) else ""
  792. self.showDoc_Instrument(Docs0, Docs[1])
  793. else:
  794. self.clearInfo_Intrument()
  795. self.callback_checkGUI(row >= 0)
  796. @pyqtSlot(int)
  797. def slot_checkSelectedBristol(self, row):
  798. if row >= 0:
  799. item = self.listBristol.item(row, 0).data(Qt.UserRole)
  800. Package, AppName, Type, ShortName, Icon, Save, Level, Features, Docs = item
  801. self.frame_Bristol.setEnabled(True)
  802. self.ico_app_bristol.setPixmap(self.getIcon(Icon).pixmap(48, 48))
  803. self.ico_builtin_fx_bristol.setPixmap(self.getIconForYesNo(Features[0]).pixmap(16, 16))
  804. self.ico_audio_input_bristol.setPixmap(self.getIconForYesNo(Features[1]).pixmap(16, 16))
  805. self.label_name_bristol.setText(AppName)
  806. self.label_midi_mode_bristol.setText(Features[2])
  807. self.label_session_level_bristol.setText(str(Level))
  808. Docs0 = Docs[0] if (os.path.exists(Docs[0].replace("file://", ""))) else ""
  809. self.showDoc_Bristol(Docs0, Docs[1])
  810. else:
  811. self.clearInfo_Bristol()
  812. self.callback_checkGUI(row >= 0)
  813. @pyqtSlot(int)
  814. def slot_checkSelectedPlugin(self, row):
  815. if row >= 0:
  816. plugin = self.listPlugin.item(row, 0).data(Qt.UserRole)
  817. self.frame_Plugin.setEnabled(True)
  818. self.ico_app_bristol.setPixmap(self.getIcon("lv2").pixmap(48, 48))
  819. self.label_name_plugin.setText(plugin["name"])
  820. self.label_plugin_audio_ins.setText(str(plugin["audioIns"]))
  821. self.label_plugin_audio_outs.setText(str(plugin["audioOuts"]))
  822. self.label_plugin_midi_ins.setText(str(plugin["midiIns"]))
  823. self.label_plugin_midi_outs.setText(str(plugin["midiOuts"]))
  824. self.label_plugin_parameter_ins.setText(str(plugin["parameterIns"]))
  825. self.label_plugin_parameter_outs.setText(str(plugin["parameterOuts"]))
  826. #Docs0 = Docs[0] if (os.path.exists(Docs[0].replace("file://", ""))) else ""
  827. #self.showDoc_Plugin(Docs0, Docs[1])
  828. else:
  829. self.clearInfo_Plugin()
  830. self.callback_checkGUI(row >= 0)
  831. @pyqtSlot(int)
  832. def slot_checkSelectedEffect(self, row):
  833. if row >= 0:
  834. item = self.listEffect.item(row, 0).data(Qt.UserRole)
  835. Package, AppName, Type, Binary, Icon, Save, Level, Features, Docs = item
  836. self.frame_Effect.setEnabled(True)
  837. self.ico_app_effect.setPixmap(self.getIcon(Icon).pixmap(48, 48))
  838. self.ico_stereo_effect.setPixmap(self.getIconForYesNo(Features[0]).pixmap(16, 16))
  839. self.label_name_effect.setText(AppName)
  840. self.label_midi_mode_effect.setText(Features[1])
  841. self.label_session_level_effect.setText(str(Level))
  842. Docs0 = Docs[0] if (os.path.exists(Docs[0].replace("file://", ""))) else ""
  843. self.showDoc_Effect(Docs0, Docs[1])
  844. else:
  845. self.clearInfo_Effect()
  846. self.callback_checkGUI(row >= 0)
  847. @pyqtSlot(int)
  848. def slot_checkSelectedTool(self, row):
  849. if row >= 0:
  850. item = self.listTool.item(row, 0).data(Qt.UserRole)
  851. Package, AppName, Type, Binary, Icon, Save, Level, Features, Docs = item
  852. self.frame_Tool.setEnabled(True)
  853. self.ico_app_tool.setPixmap(self.getIcon(Icon).pixmap(48, 48))
  854. self.label_name_tool.setText(AppName)
  855. self.label_midi_mode_tool.setText(Features[0])
  856. self.ico_jack_transport_tool.setPixmap(self.getIconForYesNo(Features[1]).pixmap(16, 16))
  857. self.label_session_level_tool.setText(str(Level))
  858. Docs0 = Docs[0] if (os.path.exists(Docs[0].replace("file://", ""))) else ""
  859. self.showDoc_Tool(Docs0, Docs[1])
  860. else:
  861. self.clearInfo_Tool()
  862. self.callback_checkGUI(row >= 0)
  863. @pyqtSlot()
  864. def slot_doubleClickedList(self):
  865. if self.m_ladish_only:
  866. self.addAppToLADISH()
  867. else:
  868. self.startApp()
  869. def saveSettings(self):
  870. if self.settings():
  871. self.settings().setValue("SplitterDAW", self.splitter_DAW.saveState())
  872. self.settings().setValue("SplitterHost", self.splitter_Host.saveState())
  873. self.settings().setValue("SplitterInstrument", self.splitter_Instrument.saveState())
  874. self.settings().setValue("SplitterBristol", self.splitter_Bristol.saveState())
  875. self.settings().setValue("SplitterPlugin", self.splitter_Plugin.saveState())
  876. self.settings().setValue("SplitterEffect", self.splitter_Effect.saveState())
  877. self.settings().setValue("SplitterTool", self.splitter_Tool.saveState())
  878. QIcon.setThemeName(self.m_lastThemeName)
  879. def loadSettings(self):
  880. if self.settings() and self.settings().contains("SplitterPlugin"):
  881. self.splitter_DAW.restoreState(self.settings().value("SplitterDAW", ""))
  882. self.splitter_Host.restoreState(self.settings().value("SplitterHost", ""))
  883. self.splitter_Instrument.restoreState(self.settings().value("SplitterInstrument", ""))
  884. self.splitter_Bristol.restoreState(self.settings().value("SplitterBristol", ""))
  885. self.splitter_Plugin.restoreState(self.settings().value("SplitterPlugin", ""))
  886. self.splitter_Effect.restoreState(self.settings().value("SplitterEffect", ""))
  887. self.splitter_Tool.restoreState(self.settings().value("SplitterTool", ""))
  888. else: # First-Run?
  889. self.splitter_DAW.setSizes([500, 200])
  890. self.splitter_Host.setSizes([500, 200])
  891. self.splitter_Instrument.setSizes([500, 200])
  892. self.splitter_Bristol.setSizes([500, 200])
  893. self.splitter_Plugin.setSizes([500, 200])
  894. self.splitter_Effect.setSizes([500, 200])
  895. self.splitter_Tool.setSizes([500, 200])
  896. # ----------------------------------------
  897. # Callbacks
  898. def callback_checkGUI(self, selected):
  899. if self.parentR():
  900. self.parentR().callback_checkGUI(selected)
  901. def callback_getProjectFolder(self):
  902. if self.parentR():
  903. return self.parentR().callback_getProjectFolder()
  904. return HOME
  905. def callback_getAppBus(self):
  906. return self.parentR().callback_getAppBus()
  907. def callback_getBPM(self):
  908. return self.parentR().callback_getBPM()
  909. def callback_getSampleRate(self):
  910. return self.parentR().callback_getSampleRate()
  911. def callback_isLadishRoom(self):
  912. return self.parentR().callback_isLadishRoom()
  913. #--------------- main ------------------
  914. if __name__ == '__main__':
  915. import dbus
  916. from signal import signal, SIG_IGN, SIGUSR1
  917. from PyQt5.QtWidgets import QApplication
  918. import jacklib, ui_claudia_launcher_app
  919. # DBus connections
  920. class DBus(object):
  921. __slots__ = [
  922. 'loopBus',
  923. 'controlBus',
  924. 'studioBus',
  925. 'appBus',
  926. ]
  927. DBus = DBus()
  928. class ClaudiaLauncherApp(QMainWindow, ui_claudia_launcher_app.Ui_ClaudiaLauncherApp):
  929. def __init__(self, parent=None):
  930. QMainWindow.__init__(self, parent)
  931. self.setupUi(self)
  932. self.settings = QSettings("Cadence", "Claudia-Launcher")
  933. self.launcher.setCallbackApp(self, self.settings, False)
  934. self.loadSettings()
  935. self.test_url = True
  936. self.test_selected = False
  937. self.studio_root_folder = HOME
  938. # Check for JACK
  939. self.jack_client = jacklib.client_open("klaudia", jacklib.JackNoStartServer, None)
  940. if not self.jack_client:
  941. QTimer.singleShot(0, self.slot_showJackError)
  942. return
  943. # Set-up GUI
  944. self.b_start.setIcon(self.getIcon("go-next"))
  945. self.b_add.setIcon(self.getIcon("list-add"))
  946. self.b_refresh.setIcon(self.getIcon("view-refresh"))
  947. self.b_open.setIcon(self.getIcon("document-open"))
  948. self.b_start.setEnabled(False)
  949. self.b_add.setEnabled(False)
  950. self.le_url.setText(self.studio_root_folder)
  951. self.co_sample_rate.addItem(str(self.getJackSampleRate()))
  952. self.sb_bpm.setValue(self.getJackBPM())
  953. self.refreshStudioList()
  954. if DBus.controlBus:
  955. self.slot_enableLADISH(True)
  956. else:
  957. for iPATH in PATH:
  958. if os.path.exists(os.path.join(iPATH, "ladishd")):
  959. break
  960. else:
  961. self.slot_enableLADISH(False)
  962. self.b_start.clicked.connect(self.slot_startApp)
  963. self.b_add.clicked.connect(self.slot_addAppToLADISH)
  964. self.b_refresh.clicked.connect(self.slot_refreshStudioList)
  965. self.co_ladi_room.currentIndexChanged[int].connect(self.slot_checkSelectedRoom)
  966. self.groupLADISH.toggled.connect(self.slot_enableLADISH)
  967. self.le_url.textChanged.connect(self.slot_checkFolderUrl)
  968. self.b_open.clicked.connect(self.slot_getAndSetPath)
  969. def getIcon(self, icon):
  970. return self.launcher.getIcon(icon)
  971. def getJackBPM(self):
  972. pos = jacklib.jack_position_t()
  973. pos.valid = 0
  974. jacklib.transport_query(self.jack_client, jacklib.pointer(pos))
  975. if pos.valid & jacklib.JackPositionBBT:
  976. return pos.beats_per_minute
  977. return 120.0
  978. def getJackSampleRate(self):
  979. return jacklib.get_sample_rate(self.jack_client)
  980. def refreshStudioList(self):
  981. self.co_ladi_room.clear()
  982. self.co_ladi_room.addItem("<Studio Root>")
  983. if DBus.controlBus:
  984. studio_bus = DBus.loopBus.get_object("org.ladish", "/org/ladish/Studio")
  985. studio_list_dump = studio_bus.GetRoomList()
  986. for i in range(len(studio_list_dump)):
  987. self.co_ladi_room.addItem("%s - %s" % (
  988. str(studio_list_dump[i][0]).replace("/org/ladish/Room", ""), studio_list_dump[i][1]['name']))
  989. # ----------------------------------------
  990. # Callbacks
  991. def callback_checkGUI(self, test_selected=None):
  992. if test_selected != None:
  993. self.test_selected = test_selected
  994. if self.test_url and self.test_selected:
  995. self.b_add.setEnabled(bool(DBus.controlBus))
  996. self.b_start.setEnabled(True)
  997. else:
  998. self.b_add.setEnabled(False)
  999. self.b_start.setEnabled(False)
  1000. def callback_getProjectFolder(self):
  1001. return self.le_url.text()
  1002. def callback_getAppBus(self):
  1003. return DBus.appBus
  1004. def callback_getBPM(self):
  1005. return self.getJackBPM()
  1006. def callback_getSampleRate(self):
  1007. return self.getJackSampleRate()
  1008. def callback_isLadishRoom(self):
  1009. return not self.le_url.isEnabled()
  1010. # ----------------------------------------
  1011. @pyqtSlot(int)
  1012. def slot_checkSelectedRoom(self, co_n):
  1013. if co_n == -1 or not DBus.controlBus:
  1014. pass
  1015. elif co_n == 0:
  1016. DBus.studioBus = DBus.loopBus.get_object("org.ladish", "/org/ladish/Studio")
  1017. DBus.appBus = dbus.Interface(DBus.studioBus, 'org.ladish.AppSupervisor')
  1018. self.b_open.setEnabled(True)
  1019. self.le_url.setEnabled(True)
  1020. self.le_url.setText(self.studio_root_folder)
  1021. else:
  1022. room_number = self.co_ladi_room.currentText().split(" ")[0]
  1023. room_name = "/org/ladish/Room" + room_number
  1024. DBus.studioBus = DBus.loopBus.get_object("org.ladish", room_name)
  1025. DBus.appBus = dbus.Interface(DBus.studioBus, 'org.ladish.AppSupervisor')
  1026. room_properties = DBus.studioBus.GetProjectProperties()
  1027. if len(room_properties[1]) > 0:
  1028. self.b_open.setEnabled(False)
  1029. self.le_url.setEnabled(False)
  1030. self.le_url.setText(room_properties[1]['dir'])
  1031. else:
  1032. self.b_open.setEnabled(True)
  1033. self.le_url.setEnabled(True)
  1034. self.studio_root_folder = self.le_url.text()
  1035. @pyqtSlot(str)
  1036. def slot_checkFolderUrl(self, url):
  1037. if os.path.exists(url):
  1038. self.test_url = True
  1039. if self.le_url.isEnabled():
  1040. self.studio_root_folder = url
  1041. else:
  1042. self.test_url = False
  1043. self.callback_checkGUI()
  1044. @pyqtSlot(bool)
  1045. def slot_enableLADISH(self, yesno):
  1046. self.groupLADISH.setCheckable(False)
  1047. if yesno:
  1048. try:
  1049. DBus.controlBus = DBus.loopBus.get_object("org.ladish", "/org/ladish/Control")
  1050. self.groupLADISH.setTitle(self.tr("LADISH is enabled"))
  1051. except:
  1052. self.groupLADISH.setEnabled(False)
  1053. self.groupLADISH.setTitle(self.tr("LADISH is sick"))
  1054. return
  1055. DBus.studioBus = DBus.loopBus.get_object("org.ladish", "/org/ladish/Studio")
  1056. DBus.appBus = dbus.Interface(DBus.studioBus, 'org.ladish.AppSupervisor')
  1057. self.refreshStudioList()
  1058. self.callback_checkGUI()
  1059. else:
  1060. self.groupLADISH.setEnabled(False)
  1061. self.groupLADISH.setTitle(self.tr("LADISH is not available"))
  1062. @pyqtSlot()
  1063. def slot_startApp(self):
  1064. self.launcher.startApp()
  1065. @pyqtSlot()
  1066. def slot_addAppToLADISH(self):
  1067. self.launcher.addAppToLADISH()
  1068. @pyqtSlot()
  1069. def slot_getAndSetPath(self):
  1070. getAndSetPath(self, self.le_url.text(), self.le_url)
  1071. @pyqtSlot()
  1072. def slot_refreshStudioList(self):
  1073. self.refreshStudioList()
  1074. @pyqtSlot()
  1075. def slot_showJackError(self):
  1076. QMessageBox.critical(self, self.tr("Error"),
  1077. self.tr("JACK is not started!\nPlease start it first, then re-run Claudia-Launcher again."))
  1078. self.close()
  1079. def saveSettings(self):
  1080. self.settings.setValue("Geometry", self.saveGeometry())
  1081. self.launcher.saveSettings()
  1082. def loadSettings(self):
  1083. self.restoreGeometry(self.settings.value("Geometry", b""))
  1084. self.launcher.loadSettings()
  1085. def closeEvent(self, event):
  1086. self.saveSettings()
  1087. if self.jack_client:
  1088. jacklib.client_close(self.jack_client)
  1089. QMainWindow.closeEvent(self, event)
  1090. # App initialization
  1091. app = QApplication(sys.argv)
  1092. app.setApplicationName("Claudia-Launcher")
  1093. app.setApplicationVersion(VERSION)
  1094. app.setOrganizationName("Cadence")
  1095. app.setWindowIcon(QIcon(":/scalable/claudia-launcher.svg"))
  1096. # Do not close on SIGUSR1
  1097. signal(SIGUSR1, SIG_IGN)
  1098. # Connect to DBus
  1099. DBus.loopBus = dbus.SessionBus()
  1100. if "org.ladish" in DBus.loopBus.list_names():
  1101. DBus.controlBus = DBus.loopBus.get_object("org.ladish", "/org/ladish/Control")
  1102. DBus.studioBus = DBus.loopBus.get_object("org.ladish", "/org/ladish/Studio")
  1103. DBus.appBus = dbus.Interface(DBus.studioBus, "org.ladish.AppSupervisor")
  1104. else:
  1105. DBus.controlBus = None
  1106. DBus.studioBus = None
  1107. DBus.appBus = None
  1108. # Show GUI
  1109. gui = ClaudiaLauncherApp()
  1110. gui.show()
  1111. # App-Loop
  1112. sys.exit(app.exec_())