Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

673 lines
22KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Common Carla code
  4. # Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation; either version 2 of
  9. # the License, or any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. import os
  20. import sys
  21. from PyQt4.QtCore import qFatal, qWarning, QDir
  22. from PyQt4.QtGui import QIcon
  23. from PyQt4.QtGui import QFileDialog, QMessageBox
  24. # ------------------------------------------------------------------------------------------------------------
  25. # Import Signal
  26. from signal import signal, SIGINT, SIGTERM
  27. try:
  28. from signal import SIGUSR1
  29. haveSIGUSR1 = True
  30. except:
  31. haveSIGUSR1 = False
  32. # ------------------------------------------------------------------------------------------------------------
  33. # Imports (Custom)
  34. from carla_backend import *
  35. # ------------------------------------------------------------------------------------------------------------
  36. # Platform specific stuff
  37. if MACOS:
  38. from PyQt4.QtGui import qt_mac_set_menubar_icons
  39. qt_mac_set_menubar_icons(False)
  40. elif WINDOWS:
  41. WINDIR = os.getenv("WINDIR")
  42. # ------------------------------------------------------------------------------------------------------------
  43. # Set Version
  44. VERSION = "1.9.0"
  45. # ------------------------------------------------------------------------------------------------------------
  46. # Set TMP
  47. envTMP = os.getenv("TMP")
  48. if envTMP is None:
  49. if WINDOWS:
  50. qWarning("TMP variable not set")
  51. TMP = QDir.tempPath()
  52. else:
  53. TMP = envTMP
  54. if not os.path.exists(TMP):
  55. qWarning("TMP does not exist")
  56. TMP = "/"
  57. del envTMP
  58. # ------------------------------------------------------------------------------------------------------------
  59. # Set HOME
  60. envHOME = os.getenv("HOME")
  61. if envHOME is None:
  62. if LINUX or MACOS:
  63. qWarning("HOME variable not set")
  64. HOME = QDir.homePath()
  65. else:
  66. HOME = envHOME
  67. if not os.path.exists(HOME):
  68. qWarning("HOME does not exist")
  69. HOME = TMP
  70. del envHOME
  71. # ------------------------------------------------------------------------------------------------------------
  72. # Set PATH
  73. envPATH = os.getenv("PATH")
  74. if envPATH is None:
  75. qWarning("PATH variable not set")
  76. if MACOS:
  77. PATH = ("/opt/local/bin", "/usr/local/bin", "/usr/bin", "/bin")
  78. elif WINDOWS:
  79. PATH = (os.path.join(WINDIR, "system32"), WINDIR)
  80. else:
  81. PATH = ("/usr/local/bin", "/usr/bin", "/bin")
  82. else:
  83. PATH = envPATH.split(os.pathsep)
  84. del envPATH
  85. # ------------------------------------------------------------------------------------------------------------
  86. # Static MIDI CC list
  87. MIDI_CC_LIST = (
  88. "0x01 Modulation",
  89. "0x02 Breath",
  90. "0x03 (Undefined)",
  91. "0x04 Foot",
  92. "0x05 Portamento",
  93. "0x07 Volume",
  94. "0x08 Balance",
  95. "0x09 (Undefined)",
  96. "0x0A Pan",
  97. "0x0B Expression",
  98. "0x0C FX Control 1",
  99. "0x0D FX Control 2",
  100. "0x0E (Undefined)",
  101. "0x0F (Undefined)",
  102. "0x10 General Purpose 1",
  103. "0x11 General Purpose 2",
  104. "0x12 General Purpose 3",
  105. "0x13 General Purpose 4",
  106. "0x14 (Undefined)",
  107. "0x15 (Undefined)",
  108. "0x16 (Undefined)",
  109. "0x17 (Undefined)",
  110. "0x18 (Undefined)",
  111. "0x19 (Undefined)",
  112. "0x1A (Undefined)",
  113. "0x1B (Undefined)",
  114. "0x1C (Undefined)",
  115. "0x1D (Undefined)",
  116. "0x1E (Undefined)",
  117. "0x1F (Undefined)",
  118. "0x46 Control 1 [Variation]",
  119. "0x47 Control 2 [Timbre]",
  120. "0x48 Control 3 [Release]",
  121. "0x49 Control 4 [Attack]",
  122. "0x4A Control 5 [Brightness]",
  123. "0x4B Control 6 [Decay]",
  124. "0x4C Control 7 [Vib Rate]",
  125. "0x4D Control 8 [Vib Depth]",
  126. "0x4E Control 9 [Vib Delay]",
  127. "0x4F Control 10 [Undefined]",
  128. "0x50 General Purpose 5",
  129. "0x51 General Purpose 6",
  130. "0x52 General Purpose 7",
  131. "0x53 General Purpose 8",
  132. "0x54 Portamento Control",
  133. "0x5B FX 1 Depth [Reverb]",
  134. "0x5C FX 2 Depth [Tremolo]",
  135. "0x5D FX 3 Depth [Chorus]",
  136. "0x5E FX 4 Depth [Detune]",
  137. "0x5F FX 5 Depth [Phaser]"
  138. )
  139. # ------------------------------------------------------------------------------------------------------------
  140. # Carla Settings keys
  141. CARLA_KEY_MAIN_PROJECT_FOLDER = "Main/ProjectFolder" # str
  142. CARLA_KEY_MAIN_USE_PRO_THEME = "Main/UseProTheme" # bool
  143. CARLA_KEY_MAIN_PRO_THEME_COLOR = "Main/ProThemeColor" # str
  144. CARLA_KEY_MAIN_REFRESH_INTERVAL = "Main/RefreshInterval" # int
  145. CARLA_KEY_CANVAS_THEME = "Canvas/Theme" # str
  146. CARLA_KEY_CANVAS_SIZE = "Canvas/Size" # str "NxN"
  147. CARLA_KEY_CANVAS_USE_BEZIER_LINES = "Canvas/UseBezierLines" # bool
  148. CARLA_KEY_CANVAS_AUTO_HIDE_GROUPS = "Canvas/AutoHideGroups" # bool
  149. CARLA_KEY_CANVAS_EYE_CANDY = "Canvas/EyeCandy" # enum
  150. CARLA_KEY_CANVAS_USE_OPENGL = "Canvas/UseOpenGL" # bool
  151. CARLA_KEY_CANVAS_ANTIALIASING = "Canvas/Antialiasing" # enum
  152. CARLA_KEY_CANVAS_HQ_ANTIALIASING = "Canvas/HQAntialiasing" # bool
  153. CARLA_KEY_CUSTOM_PAINTING = "UseCustomPainting" # bool
  154. CARLA_KEY_ENGINE_DRIVER_PREFIX = "Engine/Driver-"
  155. CARLA_KEY_ENGINE_AUDIO_DRIVER = "Engine/AudioDriver" # str
  156. CARLA_KEY_ENGINE_PROCESS_MODE = "Engine/ProcessMode" # enum
  157. CARLA_KEY_ENGINE_TRANSPORT_MODE = "Engine/TransportMode" # enum
  158. CARLA_KEY_ENGINE_FORCE_STEREO = "Engine/ForceStereo" # bool
  159. CARLA_KEY_ENGINE_PREFER_PLUGIN_BRIDGES = "Engine/PreferPluginBridges" # bool
  160. CARLA_KEY_ENGINE_PREFER_UI_BRIDGES = "Engine/PreferUiBridges" # bool
  161. CARLA_KEY_ENGINE_UIS_ALWAYS_ON_TOP = "Engine/UIsAlwaysOnTop" # bool
  162. CARLA_KEY_ENGINE_MAX_PARAMETERS = "Engine/MaxParameters" # int
  163. CARLA_KEY_ENGINE_UI_BRIDGES_TIMEOUT = "Engine/UiBridgesTimeout" # int
  164. CARLA_KEY_PATHS_LADSPA = "Paths/LADSPA"
  165. CARLA_KEY_PATHS_DSSI = "Paths/DSSI"
  166. CARLA_KEY_PATHS_LV2 = "Paths/LV2"
  167. CARLA_KEY_PATHS_VST = "Paths/VST"
  168. CARLA_KEY_PATHS_VST3 = "Paths/VST3"
  169. CARLA_KEY_PATHS_AU = "Paths/AU"
  170. CARLA_KEY_PATHS_CSD = "Paths/CSD"
  171. CARLA_KEY_PATHS_GIG = "Paths/GIG"
  172. CARLA_KEY_PATHS_SF2 = "Paths/SF2"
  173. CARLA_KEY_PATHS_SFZ = "Paths/SFZ"
  174. # ------------------------------------------------------------------------------------------------------------
  175. # Global Carla object
  176. class CarlaObject(object):
  177. __slots__ = [
  178. # Host library object
  179. 'host',
  180. # Host Window
  181. 'gui',
  182. # bool, is controller
  183. 'isControl',
  184. # bool, is running local
  185. 'isLocal',
  186. # bool, is plugin
  187. 'isPlugin',
  188. # current buffer size
  189. 'bufferSize',
  190. # current sample rate
  191. 'sampleRate',
  192. # current process mode
  193. 'processMode',
  194. # current transport mode
  195. 'transportMode',
  196. # current max parameters
  197. 'maxParameters',
  198. # discovery tools
  199. 'discovery_native',
  200. 'discovery_posix32',
  201. 'discovery_posix64',
  202. 'discovery_win32',
  203. 'discovery_win64',
  204. # default paths
  205. 'DEFAULT_LADSPA_PATH',
  206. 'DEFAULT_DSSI_PATH',
  207. 'DEFAULT_LV2_PATH',
  208. 'DEFAULT_VST_PATH',
  209. 'DEFAULT_VST3_PATH',
  210. 'DEFAULT_AU_PATH',
  211. 'DEFAULT_CSOUND_PATH',
  212. 'DEFAULT_GIG_PATH',
  213. 'DEFAULT_SF2_PATH',
  214. 'DEFAULT_SFZ_PATH'
  215. ]
  216. gCarla = CarlaObject()
  217. gCarla.host = None
  218. gCarla.gui = None
  219. gCarla.isControl = False
  220. gCarla.isLocal = True
  221. gCarla.isPlugin = False
  222. gCarla.bufferSize = 0
  223. gCarla.sampleRate = 0.0
  224. gCarla.processMode = ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS if LINUX else ENGINE_PROCESS_MODE_CONTINUOUS_RACK
  225. gCarla.transportMode = ENGINE_TRANSPORT_MODE_JACK if LINUX else ENGINE_TRANSPORT_MODE_INTERNAL
  226. gCarla.maxParameters = MAX_DEFAULT_PARAMETERS
  227. gCarla.discovery_native = ""
  228. gCarla.discovery_posix32 = ""
  229. gCarla.discovery_posix64 = ""
  230. gCarla.discovery_win32 = ""
  231. gCarla.discovery_win64 = ""
  232. # ------------------------------------------------------------------------------------------------------------
  233. # Default Plugin Folders (get)
  234. DEFAULT_LADSPA_PATH = ""
  235. DEFAULT_DSSI_PATH = ""
  236. DEFAULT_LV2_PATH = ""
  237. DEFAULT_VST_PATH = ""
  238. DEFAULT_VST3_PATH = ""
  239. DEFAULT_AU_PATH = ""
  240. DEFAULT_CSOUND_PATH = ""
  241. DEFAULT_GIG_PATH = ""
  242. DEFAULT_SF2_PATH = ""
  243. DEFAULT_SFZ_PATH = ""
  244. if WINDOWS:
  245. splitter = ";"
  246. APPDATA = os.getenv("APPDATA")
  247. PROGRAMFILES = os.getenv("PROGRAMFILES")
  248. PROGRAMFILESx86 = os.getenv("PROGRAMFILES(x86)")
  249. COMMONPROGRAMFILES = os.getenv("COMMONPROGRAMFILES")
  250. # Small integrity tests
  251. if not APPDATA:
  252. qFatal("APPDATA variable not set, cannot continue")
  253. sys.exit(1)
  254. if not PROGRAMFILES:
  255. qFatal("PROGRAMFILES variable not set, cannot continue")
  256. sys.exit(1)
  257. if not COMMONPROGRAMFILES:
  258. qFatal("COMMONPROGRAMFILES variable not set, cannot continue")
  259. sys.exit(1)
  260. DEFAULT_LADSPA_PATH = APPDATA + "\\LADSPA"
  261. DEFAULT_LADSPA_PATH += ";" + PROGRAMFILES + "\\LADSPA"
  262. DEFAULT_DSSI_PATH = APPDATA + "\\DSSI"
  263. DEFAULT_DSSI_PATH += ";" + PROGRAMFILES + "\\DSSI"
  264. DEFAULT_LV2_PATH = APPDATA + "\\LV2"
  265. DEFAULT_LV2_PATH += ";" + COMMONPROGRAMFILES + "\\LV2"
  266. DEFAULT_VST_PATH = PROGRAMFILES + "\\VstPlugins"
  267. DEFAULT_VST_PATH += ";" + PROGRAMFILES + "\\Steinberg\\VstPlugins"
  268. DEFAULT_VST3_PATH = PROGRAMFILES + "\\Vst3"
  269. DEFAULT_GIG_PATH = APPDATA + "\\GIG"
  270. DEFAULT_SF2_PATH = APPDATA + "\\SF2"
  271. DEFAULT_SFZ_PATH = APPDATA + "\\SFZ"
  272. if PROGRAMFILESx86:
  273. DEFAULT_LADSPA_PATH += ";" + PROGRAMFILESx86 + "\\LADSPA"
  274. DEFAULT_DSSI_PATH += ";" + PROGRAMFILESx86 + "\\DSSI"
  275. DEFAULT_VST_PATH += ";" + PROGRAMFILESx86 + "\\VstPlugins"
  276. DEFAULT_VST_PATH += ";" + PROGRAMFILESx86 + "\\Steinberg\\VstPlugins"
  277. elif HAIKU:
  278. splitter = ":"
  279. DEFAULT_LADSPA_PATH = HOME + "/.ladspa"
  280. DEFAULT_LADSPA_PATH += ":/boot/common/add-ons/ladspa"
  281. DEFAULT_DSSI_PATH = HOME + "/.dssi"
  282. DEFAULT_DSSI_PATH += ":/boot/common/add-ons/dssi"
  283. DEFAULT_LV2_PATH = HOME + "/.lv2"
  284. DEFAULT_LV2_PATH += ":/boot/common/add-ons/lv2"
  285. DEFAULT_VST_PATH = HOME + "/.vst"
  286. DEFAULT_VST_PATH += ":/boot/common/add-ons/vst"
  287. DEFAULT_VST3_PATH = HOME + "/.vst3"
  288. DEFAULT_VST3_PATH += ":/boot/common/add-ons/vst3"
  289. elif MACOS:
  290. splitter = ":"
  291. DEFAULT_LADSPA_PATH = HOME + "/Library/Audio/Plug-Ins/LADSPA"
  292. DEFAULT_LADSPA_PATH += ":/Library/Audio/Plug-Ins/LADSPA"
  293. DEFAULT_DSSI_PATH = HOME + "/Library/Audio/Plug-Ins/DSSI"
  294. DEFAULT_DSSI_PATH += ":/Library/Audio/Plug-Ins/DSSI"
  295. DEFAULT_LV2_PATH = HOME + "/Library/Audio/Plug-Ins/LV2"
  296. DEFAULT_LV2_PATH += ":/Library/Audio/Plug-Ins/LV2"
  297. DEFAULT_VST_PATH = HOME + "/Library/Audio/Plug-Ins/VST"
  298. DEFAULT_VST_PATH += ":/Library/Audio/Plug-Ins/VST"
  299. DEFAULT_VST3_PATH = HOME + "/Library/Audio/Plug-Ins/VST3"
  300. DEFAULT_VST3_PATH += ":/Library/Audio/Plug-Ins/VST3"
  301. DEFAULT_AU_PATH = HOME + "/Library/Audio/Plug-Ins/Components"
  302. DEFAULT_AU_PATH += ":/Library/Audio/Plug-Ins/Components"
  303. else:
  304. splitter = ":"
  305. DEFAULT_LADSPA_PATH = HOME + "/.ladspa"
  306. DEFAULT_LADSPA_PATH += ":/usr/lib/ladspa"
  307. DEFAULT_LADSPA_PATH += ":/usr/local/lib/ladspa"
  308. DEFAULT_DSSI_PATH = HOME + "/.dssi"
  309. DEFAULT_DSSI_PATH += ":/usr/lib/dssi"
  310. DEFAULT_DSSI_PATH += ":/usr/local/lib/dssi"
  311. DEFAULT_LV2_PATH = HOME + "/.lv2"
  312. DEFAULT_LV2_PATH += ":/usr/lib/lv2"
  313. DEFAULT_LV2_PATH += ":/usr/local/lib/lv2"
  314. DEFAULT_VST_PATH = HOME + "/.vst"
  315. DEFAULT_VST_PATH += ":/usr/lib/vst"
  316. DEFAULT_VST_PATH += ":/usr/local/lib/vst"
  317. DEFAULT_VST3_PATH = HOME + "/.vst3"
  318. DEFAULT_VST3_PATH += ":/usr/lib/vst3"
  319. DEFAULT_VST3_PATH += ":/usr/local/lib/vst3"
  320. DEFAULT_GIG_PATH = HOME + "/.sounds/gig"
  321. DEFAULT_GIG_PATH += ":/usr/share/sounds/gig"
  322. DEFAULT_SF2_PATH = HOME + "/.sounds/sf2"
  323. DEFAULT_SF2_PATH += ":/usr/share/sounds/sf2"
  324. DEFAULT_SFZ_PATH = HOME + "/.sounds/sfz"
  325. DEFAULT_SFZ_PATH += ":/usr/share/sounds/sfz"
  326. # ------------------------------------------------------------------------------------------------------------
  327. # Default Plugin Folders (set)
  328. readEnvVars = True
  329. if WINDOWS:
  330. # Check if running Wine. If yes, ignore env vars
  331. from winreg import ConnectRegistry, OpenKey, CloseKey, HKEY_CURRENT_USER
  332. reg = ConnectRegistry(None, HKEY_CURRENT_USER)
  333. try:
  334. key = OpenKey(reg, r"SOFTWARE\Wine")
  335. CloseKey(key)
  336. readEnvVars = False
  337. except:
  338. pass
  339. CloseKey(reg)
  340. del reg
  341. if readEnvVars:
  342. gCarla.DEFAULT_LADSPA_PATH = os.getenv("LADSPA_PATH", DEFAULT_LADSPA_PATH).split(splitter)
  343. gCarla.DEFAULT_DSSI_PATH = os.getenv("DSSI_PATH", DEFAULT_DSSI_PATH).split(splitter)
  344. gCarla.DEFAULT_LV2_PATH = os.getenv("LV2_PATH", DEFAULT_LV2_PATH).split(splitter)
  345. gCarla.DEFAULT_VST_PATH = os.getenv("VST_PATH", DEFAULT_VST_PATH).split(splitter)
  346. gCarla.DEFAULT_VST3_PATH = os.getenv("VST3_PATH", DEFAULT_VST3_PATH).split(splitter)
  347. gCarla.DEFAULT_AU_PATH = os.getenv("AU_PATH", DEFAULT_AU_PATH).split(splitter)
  348. gCarla.DEFAULT_CSOUND_PATH = os.getenv("CSOUND_PATH", DEFAULT_CSOUND_PATH).split(splitter)
  349. gCarla.DEFAULT_GIG_PATH = os.getenv("GIG_PATH", DEFAULT_GIG_PATH).split(splitter)
  350. gCarla.DEFAULT_SF2_PATH = os.getenv("SF2_PATH", DEFAULT_SF2_PATH).split(splitter)
  351. gCarla.DEFAULT_SFZ_PATH = os.getenv("SFZ_PATH", DEFAULT_SFZ_PATH).split(splitter)
  352. else:
  353. gCarla.DEFAULT_LADSPA_PATH = DEFAULT_LADSPA_PATH.split(splitter)
  354. gCarla.DEFAULT_DSSI_PATH = DEFAULT_DSSI_PATH.split(splitter)
  355. gCarla.DEFAULT_LV2_PATH = DEFAULT_LV2_PATH.split(splitter)
  356. gCarla.DEFAULT_VST_PATH = DEFAULT_VST_PATH.split(splitter)
  357. gCarla.DEFAULT_VST3_PATH = DEFAULT_VST3_PATH.split(splitter)
  358. gCarla.DEFAULT_AU_PATH = DEFAULT_AU_PATH.split(splitter)
  359. gCarla.DEFAULT_CSOUND_PATH = DEFAULT_CSOUND_PATH.split(splitter)
  360. gCarla.DEFAULT_GIG_PATH = DEFAULT_GIG_PATH.split(splitter)
  361. gCarla.DEFAULT_SF2_PATH = DEFAULT_SF2_PATH.split(splitter)
  362. gCarla.DEFAULT_SFZ_PATH = DEFAULT_SFZ_PATH.split(splitter)
  363. # ------------------------------------------------------------------------------------------------------------
  364. # Search for Carla tools
  365. CWD = sys.path[0]
  366. # make it work with cxfreeze
  367. if CWD.endswith("/carla"):
  368. CWD = CWD.rsplit("/carla", 1)[0]
  369. elif CWD.endswith("\\carla.exe"):
  370. CWD = CWD.rsplit("\\carla.exe", 1)[0]
  371. # find tool
  372. def findTool(toolDir, toolName):
  373. path = os.path.join(CWD, toolDir, toolName)
  374. if os.path.exists(path):
  375. return path
  376. for p in PATH:
  377. path = os.path.join(p, toolName)
  378. if os.path.exists(path):
  379. return path
  380. return ""
  381. # ------------------------------------------------------------------------------------------------------------
  382. # Init host
  383. def initHost(appName, libPrefix = None, failError = True):
  384. # -------------------------------------------------------------
  385. # Set Carla library name
  386. libname = "libcarla_"
  387. if gCarla.isControl:
  388. libname += "control2"
  389. else:
  390. libname += "standalone2"
  391. if WINDOWS:
  392. libname += ".dll"
  393. elif MACOS:
  394. libname += ".dylib"
  395. else:
  396. libname += ".so"
  397. # -------------------------------------------------------------
  398. # Search for the Carla library
  399. libfilename = ""
  400. if libPrefix is not None:
  401. libfilename = os.path.join(libPrefix, "lib", "carla", libname)
  402. else:
  403. path = os.path.join(CWD, "backend", libname)
  404. if os.path.exists(path):
  405. libfilename = path
  406. else:
  407. path = os.getenv("CARLA_LIB_PATH")
  408. if path and os.path.exists(path):
  409. CARLA_LIB_PATH = (path,)
  410. elif WINDOWS:
  411. CARLA_LIB_PATH = (os.path.join(PROGRAMFILES, "Carla"),)
  412. elif MACOS:
  413. CARLA_LIB_PATH = ("/opt/local/lib", "/usr/local/lib/", "/usr/lib")
  414. else:
  415. CARLA_LIB_PATH = ("/usr/local/lib/", "/usr/lib")
  416. for libpath in CARLA_LIB_PATH:
  417. path = os.path.join(libpath, "carla", libname)
  418. if os.path.exists(path):
  419. libfilename = path
  420. break
  421. # -------------------------------------------------------------
  422. # find windows tools
  423. gCarla.discovery_win32 = findTool("discovery", "carla-discovery-win32.exe")
  424. gCarla.discovery_win64 = findTool("discovery", "carla-discovery-win64.exe")
  425. # -------------------------------------------------------------
  426. # find native and posix tools
  427. if not WINDOWS:
  428. gCarla.discovery_native = findTool("discovery", "carla-discovery-native")
  429. gCarla.discovery_posix32 = findTool("discovery", "carla-discovery-posix32")
  430. gCarla.discovery_posix64 = findTool("discovery", "carla-discovery-posix64")
  431. # -------------------------------------------------------------
  432. if not (libfilename or gCarla.isPlugin):
  433. if failError:
  434. QMessageBox.critical(None, "Error", "Failed to find the carla library, cannot continue")
  435. sys.exit(1)
  436. return
  437. # -------------------------------------------------------------
  438. # Init host
  439. if gCarla.host is None:
  440. gCarla.host = Host(libfilename)
  441. # -------------------------------------------------------------
  442. # Set binary path
  443. libfolder = libfilename.replace(libname, "")
  444. localBinaries = os.path.join(libfolder, "..", "bridges")
  445. systemBinaries = os.path.join(libfolder, "bridges")
  446. if os.path.exists(libfolder):
  447. gCarla.host.set_engine_option(ENGINE_OPTION_PATH_BINARIES, 0, libfolder)
  448. elif os.path.exists(localBinaries):
  449. gCarla.host.set_engine_option(ENGINE_OPTION_PATH_BINARIES, 0, localBinaries)
  450. elif os.path.exists(systemBinaries):
  451. gCarla.host.set_engine_option(ENGINE_OPTION_PATH_BINARIES, 0, systemBinaries)
  452. # -------------------------------------------------------------
  453. # Set resource path
  454. localResources = os.path.join(libfolder, "..", "modules", "native-plugins", "resources")
  455. systemResources = os.path.join(libfolder, "resources")
  456. if os.path.exists(localResources):
  457. gCarla.host.set_engine_option(ENGINE_OPTION_PATH_RESOURCES, 0, localResources)
  458. elif os.path.exists(systemResources):
  459. gCarla.host.set_engine_option(ENGINE_OPTION_PATH_RESOURCES, 0, systemResources)
  460. # ------------------------------------------------------------------------------------------------------------
  461. # Check if a value is a number (float support)
  462. def isNumber(value):
  463. try:
  464. float(value)
  465. return True
  466. except:
  467. return False
  468. # ------------------------------------------------------------------------------------------------------------
  469. # Convert a value to a list
  470. def toList(value):
  471. if value is None:
  472. return []
  473. elif not isinstance(value, list):
  474. return [value]
  475. else:
  476. return value
  477. # ------------------------------------------------------------------------------------------------------------
  478. # Get Icon from user theme, using our own as backup (Oxygen)
  479. def getIcon(icon, size=16):
  480. return QIcon.fromTheme(icon, QIcon(":/%ix%i/%s.png" % (size, size, icon)))
  481. # ------------------------------------------------------------------------------------------------------------
  482. # Signal handler
  483. def signalHandler(sig, frame):
  484. if gCarla.gui is None:
  485. return
  486. if sig in (SIGINT, SIGTERM):
  487. gCarla.gui.SIGTERM.emit()
  488. elif haveSIGUSR1 and sig == SIGUSR1:
  489. gCarla.gui.SIGUSR1.emit()
  490. def setUpSignals():
  491. signal(SIGINT, signalHandler)
  492. signal(SIGTERM, signalHandler)
  493. if not haveSIGUSR1:
  494. return
  495. signal(SIGUSR1, signalHandler)
  496. # ------------------------------------------------------------------------------------------------------------
  497. # QLineEdit and QPushButton combo
  498. def getAndSetPath(parent, currentPath, lineEdit):
  499. newPath = QFileDialog.getExistingDirectory(parent, parent.tr("Set Path"), currentPath, QFileDialog.ShowDirsOnly)
  500. if newPath:
  501. lineEdit.setText(newPath)
  502. return newPath
  503. # ------------------------------------------------------------------------------------------------------------
  504. # Get plugin type as string
  505. def getPluginTypeAsString(ptype):
  506. if ptype == PLUGIN_INTERNAL:
  507. return "Internal"
  508. if ptype == PLUGIN_LADSPA:
  509. return "LADSPA"
  510. if ptype == PLUGIN_DSSI:
  511. return "DSSI"
  512. if ptype == PLUGIN_LV2:
  513. return "LV2"
  514. if ptype == PLUGIN_VST:
  515. return "VST"
  516. if ptype == PLUGIN_VST3:
  517. return "VST3"
  518. if ptype == PLUGIN_AU:
  519. return "AU"
  520. if ptype == PLUGIN_JACK:
  521. return "JACK"
  522. if ptype == PLUGIN_REWIRE:
  523. return "ReWire"
  524. if ptype == PLUGIN_FILE_CSD:
  525. return "CSD"
  526. if ptype == PLUGIN_FILE_GIG:
  527. return "GIG"
  528. if ptype == PLUGIN_FILE_SF2:
  529. return "SF2"
  530. if ptype == PLUGIN_FILE_SFZ:
  531. return "SFZ"
  532. return "Unknown"
  533. # ------------------------------------------------------------------------------------------------------------
  534. # Custom MessageBox
  535. def CustomMessageBox(parent, icon, title, text, extraText="", buttons=QMessageBox.Yes|QMessageBox.No, defButton=QMessageBox.No):
  536. msgBox = QMessageBox(parent)
  537. msgBox.setIcon(icon)
  538. msgBox.setWindowTitle(title)
  539. msgBox.setText(text)
  540. msgBox.setInformativeText(extraText)
  541. msgBox.setStandardButtons(buttons)
  542. msgBox.setDefaultButton(defButton)
  543. return msgBox.exec_()