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.

1366 lines
57KB

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