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.

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