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

carla_shared.py 25KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Common Carla code
  4. # Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation; either version 2 of
  9. # the License, or any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. import os
  20. import sys
  21. try:
  22. from PyQt5.QtCore import qFatal, qWarning
  23. from PyQt5.QtGui import QIcon
  24. from PyQt5.QtWidgets import QFileDialog, QMessageBox
  25. except:
  26. from PyQt4.QtCore import qFatal, qWarning
  27. from PyQt4.QtGui import QIcon
  28. from PyQt4.QtGui import QFileDialog, QMessageBox
  29. # ------------------------------------------------------------------------------------------------------------
  30. # Import Signal
  31. from signal import signal, SIGINT, SIGTERM
  32. try:
  33. from signal import SIGUSR1
  34. haveSIGUSR1 = True
  35. except:
  36. haveSIGUSR1 = False
  37. # ------------------------------------------------------------------------------------------------------------
  38. # Imports (Custom)
  39. from carla_backend import *
  40. # ------------------------------------------------------------------------------------------------------------
  41. # Platform specific stuff
  42. if MACOS:
  43. from PyQt5.QtGui import qt_mac_set_menubar_icons
  44. qt_mac_set_menubar_icons(False)
  45. elif WINDOWS:
  46. WINDIR = os.getenv("WINDIR")
  47. # ------------------------------------------------------------------------------------------------------------
  48. # Set Version
  49. VERSION = "1.9.0"
  50. # ------------------------------------------------------------------------------------------------------------
  51. # Set TMP
  52. TMP = os.getenv("TMP")
  53. if TMP is None:
  54. if WINDOWS:
  55. qWarning("TMP variable not set")
  56. TMP = os.path.join(WINDIR, "temp")
  57. else:
  58. TMP = "/tmp"
  59. elif not os.path.exists(TMP):
  60. qWarning("TMP does not exist")
  61. TMP = "/tmp"
  62. # ------------------------------------------------------------------------------------------------------------
  63. # Set HOME
  64. HOME = os.getenv("HOME")
  65. if HOME is None:
  66. HOME = os.path.expanduser("~")
  67. if LINUX or MACOS:
  68. qWarning("HOME variable not set")
  69. if not os.path.exists(HOME):
  70. qWarning("HOME does not exist")
  71. HOME = TMP
  72. # ------------------------------------------------------------------------------------------------------------
  73. # Set PATH
  74. PATH = os.getenv("PATH")
  75. if PATH is None:
  76. qWarning("PATH variable not set")
  77. if MACOS:
  78. PATH = ("/opt/local/bin", "/usr/local/bin", "/usr/bin", "/bin")
  79. elif WINDOWS:
  80. PATH = (os.path.join(WINDIR, "system32"), WINDIR)
  81. else:
  82. PATH = ("/usr/local/bin", "/usr/bin", "/bin")
  83. else:
  84. PATH = PATH.split(os.pathsep)
  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. # Default Plugin Folders (get)
  141. if WINDOWS:
  142. splitter = ";"
  143. APPDATA = os.getenv("APPDATA")
  144. PROGRAMFILES = os.getenv("PROGRAMFILES")
  145. PROGRAMFILESx86 = os.getenv("PROGRAMFILES(x86)")
  146. COMMONPROGRAMFILES = os.getenv("COMMONPROGRAMFILES")
  147. # Small integrity tests
  148. if not APPDATA:
  149. qFatal("APPDATA variable not set, cannot continue")
  150. sys.exit(1)
  151. if not PROGRAMFILES:
  152. qFatal("PROGRAMFILES variable not set, cannot continue")
  153. sys.exit(1)
  154. if not COMMONPROGRAMFILES:
  155. qFatal("COMMONPROGRAMFILES variable not set, cannot continue")
  156. sys.exit(1)
  157. DEFAULT_LADSPA_PATH = ";".join((os.path.join(APPDATA, "LADSPA"),
  158. os.path.join(PROGRAMFILES, "LADSPA")))
  159. DEFAULT_DSSI_PATH = ";".join((os.path.join(APPDATA, "DSSI"),
  160. os.path.join(PROGRAMFILES, "DSSI")))
  161. DEFAULT_LV2_PATH = ";".join((os.path.join(APPDATA, "LV2"),
  162. os.path.join(COMMONPROGRAMFILES, "LV2")))
  163. DEFAULT_VST_PATH = ";".join((os.path.join(PROGRAMFILES, "VstPlugins"),
  164. os.path.join(PROGRAMFILES, "Steinberg", "VstPlugins")))
  165. DEFAULT_AU_PATH = ""
  166. # TODO
  167. DEFAULT_CSOUND_PATH = ""
  168. DEFAULT_GIG_PATH = ";".join((os.path.join(APPDATA, "GIG"),))
  169. DEFAULT_SF2_PATH = ";".join((os.path.join(APPDATA, "SF2"),))
  170. DEFAULT_SFZ_PATH = ";".join((os.path.join(APPDATA, "SFZ"),))
  171. if PROGRAMFILESx86:
  172. DEFAULT_LADSPA_PATH += ";"+os.path.join(PROGRAMFILESx86, "LADSPA")
  173. DEFAULT_DSSI_PATH += ";"+os.path.join(PROGRAMFILESx86, "DSSI")
  174. DEFAULT_VST_PATH += ";"+os.path.join(PROGRAMFILESx86, "VstPlugins")
  175. DEFAULT_VST_PATH += ";"+os.path.join(PROGRAMFILESx86, "Steinberg", "VstPlugins")
  176. elif HAIKU:
  177. splitter = ":"
  178. DEFAULT_LADSPA_PATH = ":".join((os.path.join(HOME, ".ladspa"),
  179. os.path.join("/", "boot", "common", "add-ons", "ladspa")))
  180. DEFAULT_DSSI_PATH = ":".join((os.path.join(HOME, ".dssi"),
  181. os.path.join("/", "boot", "common", "add-ons", "dssi")))
  182. DEFAULT_LV2_PATH = ":".join((os.path.join(HOME, ".lv2"),
  183. os.path.join("/", "boot", "common", "add-ons", "lv2")))
  184. DEFAULT_VST_PATH = ":".join((os.path.join(HOME, ".vst"),
  185. os.path.join("/", "boot", "common", "add-ons", "vst")))
  186. DEFAULT_AU_PATH = ""
  187. # TODO
  188. DEFAULT_CSOUND_PATH = ""
  189. # TODO
  190. DEFAULT_GIG_PATH = ""
  191. DEFAULT_SF2_PATH = ""
  192. DEFAULT_SFZ_PATH = ""
  193. elif MACOS:
  194. splitter = ":"
  195. DEFAULT_LADSPA_PATH = ":".join((os.path.join(HOME, "Library", "Audio", "Plug-Ins", "LADSPA"),
  196. os.path.join("/", "Library", "Audio", "Plug-Ins", "LADSPA")))
  197. DEFAULT_DSSI_PATH = ":".join((os.path.join(HOME, "Library", "Audio", "Plug-Ins", "DSSI"),
  198. os.path.join("/", "Library", "Audio", "Plug-Ins", "DSSI")))
  199. DEFAULT_LV2_PATH = ":".join((os.path.join(HOME, "Library", "Audio", "Plug-Ins", "LV2"),
  200. os.path.join("/", "Library", "Audio", "Plug-Ins", "LV2")))
  201. DEFAULT_VST_PATH = ":".join((os.path.join(HOME, "Library", "Audio", "Plug-Ins", "VST"),
  202. os.path.join("/", "Library", "Audio", "Plug-Ins", "VST")))
  203. DEFAULT_AU_PATH = ":".join((os.path.join(HOME, "Library", "Audio", "Plug-Ins", "Components"),
  204. os.path.join("/", "Library", "Audio", "Plug-Ins", "Components")))
  205. # TODO
  206. DEFAULT_CSOUND_PATH = ""
  207. # TODO
  208. DEFAULT_GIG_PATH = ""
  209. DEFAULT_SF2_PATH = ""
  210. DEFAULT_SFZ_PATH = ""
  211. else:
  212. splitter = ":"
  213. DEFAULT_LADSPA_PATH = ":".join((os.path.join(HOME, ".ladspa"),
  214. os.path.join("/", "usr", "lib", "ladspa"),
  215. os.path.join("/", "usr", "local", "lib", "ladspa")))
  216. DEFAULT_DSSI_PATH = ":".join((os.path.join(HOME, ".dssi"),
  217. os.path.join("/", "usr", "lib", "dssi"),
  218. os.path.join("/", "usr", "local", "lib", "dssi")))
  219. DEFAULT_LV2_PATH = ":".join((os.path.join(HOME, ".lv2"),
  220. os.path.join("/", "usr", "lib", "lv2"),
  221. os.path.join("/", "usr", "local", "lib", "lv2")))
  222. DEFAULT_VST_PATH = ":".join((os.path.join(HOME, ".vst"),
  223. os.path.join("/", "usr", "lib", "vst"),
  224. os.path.join("/", "usr", "local", "lib", "vst")))
  225. DEFAULT_AU_PATH = ""
  226. # TODO
  227. DEFAULT_CSOUND_PATH = ""
  228. DEFAULT_GIG_PATH = ":".join((os.path.join(HOME, ".sounds", "gig"),
  229. os.path.join("/", "usr", "share", "sounds", "gig")))
  230. DEFAULT_SF2_PATH = ":".join((os.path.join(HOME, ".sounds", "sf2"),
  231. os.path.join("/", "usr", "share", "sounds", "sf2")))
  232. DEFAULT_SFZ_PATH = ":".join((os.path.join(HOME, ".sounds", "sfz"),
  233. os.path.join("/", "usr", "share", "sounds", "sfz")))
  234. # ------------------------------------------------------------------------------------------------------------
  235. # Carla Settings keys
  236. CARLA_KEY_MAIN_PROJECT_FOLDER = "Main/ProjectFolder" # str
  237. CARLA_KEY_MAIN_USE_PRO_THEME = "Main/UseProTheme" # bool
  238. CARLA_KEY_MAIN_PRO_THEME_COLOR = "Main/ProThemeColor" # str
  239. CARLA_KEY_MAIN_REFRESH_INTERVAL = "Main/RefreshInterval" # int
  240. CARLA_KEY_CANVAS_THEME = "Canvas/Theme" # str
  241. CARLA_KEY_CANVAS_SIZE = "Canvas/Size" # str "NxN"
  242. CARLA_KEY_CANVAS_USE_BEZIER_LINES = "Canvas/UseBezierLines" # bool
  243. CARLA_KEY_CANVAS_AUTO_HIDE_GROUPS = "Canvas/AutoHideGroups" # bool
  244. CARLA_KEY_CANVAS_EYE_CANDY = "Canvas/EyeCandy" # enum
  245. CARLA_KEY_CANVAS_USE_OPENGL = "Canvas/UseOpenGL" # bool
  246. CARLA_KEY_CANVAS_ANTIALIASING = "Canvas/Antialiasing" # enum
  247. CARLA_KEY_CANVAS_HQ_ANTIALIASING = "Canvas/HQAntialiasing" # bool
  248. CARLA_KEY_ENGINE_DRIVER_PREFIX = "Engine/Driver-"
  249. CARLA_KEY_ENGINE_AUDIO_DRIVER = "Engine/AudioDriver" # str
  250. CARLA_KEY_ENGINE_PROCESS_MODE = "Engine/ProcessMode" # enum
  251. CARLA_KEY_ENGINE_FORCE_STEREO = "Engine/ForceStereo" # bool
  252. CARLA_KEY_ENGINE_PREFER_PLUGIN_BRIDGES = "Engine/PreferPluginBridges" # bool
  253. CARLA_KEY_ENGINE_PREFER_UI_BRIDGES = "Engine/PreferUiBridges" # bool
  254. CARLA_KEY_ENGINE_UIS_ALWAYS_ON_TOP = "Engine/UIsAlwaysOnTop" # bool
  255. CARLA_KEY_ENGINE_MAX_PARAMETERS = "Engine/MaxParameters" # int
  256. CARLA_KEY_ENGINE_UI_BRIDGES_TIMEOUT = "Engine/UiBridgesTimeout" # int
  257. CARLA_KEY_PATHS_LADSPA = "Paths/LADSPA"
  258. CARLA_KEY_PATHS_DSSI = "Paths/DSSI"
  259. CARLA_KEY_PATHS_LV2 = "Paths/LV2"
  260. CARLA_KEY_PATHS_VST = "Paths/VST"
  261. CARLA_KEY_PATHS_AU = "Paths/AU"
  262. CARLA_KEY_PATHS_CSOUND = "Paths/CSOUND"
  263. CARLA_KEY_PATHS_GIG = "Paths/GIG"
  264. CARLA_KEY_PATHS_SF2 = "Paths/SF2"
  265. CARLA_KEY_PATHS_SFZ = "Paths/SFZ"
  266. # ------------------------------------------------------------------------------------------------------------
  267. # Global Carla object
  268. class CarlaObject(object):
  269. __slots__ = [
  270. # Host library object
  271. 'host',
  272. # Host Window
  273. 'gui',
  274. # bool, is controller
  275. 'isControl',
  276. # bool, is running local
  277. 'isLocal',
  278. # bool, is plugin
  279. 'isPlugin',
  280. # current process mode
  281. 'processMode',
  282. # current max parameters
  283. 'maxParameters',
  284. # discovery tools
  285. 'discovery_native',
  286. 'discovery_posix32',
  287. 'discovery_posix64',
  288. 'discovery_win32',
  289. 'discovery_win64',
  290. # default paths
  291. 'DEFAULT_LADSPA_PATH',
  292. 'DEFAULT_DSSI_PATH',
  293. 'DEFAULT_LV2_PATH',
  294. 'DEFAULT_VST_PATH',
  295. 'DEFAULT_AU_PATH',
  296. 'DEFAULT_CSOUND_PATH',
  297. 'DEFAULT_GIG_PATH',
  298. 'DEFAULT_SF2_PATH',
  299. 'DEFAULT_SFZ_PATH'
  300. ]
  301. Carla = CarlaObject()
  302. Carla.host = None
  303. Carla.gui = None
  304. Carla.isControl = False
  305. Carla.isLocal = True
  306. Carla.isPlugin = False
  307. Carla.processMode = PROCESS_MODE_MULTIPLE_CLIENTS if LINUX else PROCESS_MODE_CONTINUOUS_RACK
  308. Carla.maxParameters = MAX_DEFAULT_PARAMETERS
  309. Carla.discovery_native = ""
  310. Carla.discovery_posix32 = ""
  311. Carla.discovery_posix64 = ""
  312. Carla.discovery_win32 = ""
  313. Carla.discovery_win64 = ""
  314. # ------------------------------------------------------------------------------------------------------------
  315. # Default Plugin Folders (set)
  316. readEnvVars = True
  317. if WINDOWS:
  318. # Check if running Wine. If yes, ignore env vars
  319. from winreg import ConnectRegistry, OpenKey, CloseKey, HKEY_CURRENT_USER
  320. reg = ConnectRegistry(None, HKEY_CURRENT_USER)
  321. try:
  322. key = OpenKey(reg, r"SOFTWARE\Wine")
  323. CloseKey(key)
  324. readEnvVars = False
  325. except:
  326. pass
  327. CloseKey(reg)
  328. del reg
  329. if readEnvVars:
  330. Carla.DEFAULT_LADSPA_PATH = os.getenv("LADSPA_PATH", DEFAULT_LADSPA_PATH).split(splitter)
  331. Carla.DEFAULT_DSSI_PATH = os.getenv("DSSI_PATH", DEFAULT_DSSI_PATH).split(splitter)
  332. Carla.DEFAULT_LV2_PATH = os.getenv("LV2_PATH", DEFAULT_LV2_PATH).split(splitter)
  333. Carla.DEFAULT_VST_PATH = os.getenv("VST_PATH", DEFAULT_VST_PATH).split(splitter)
  334. Carla.DEFAULT_AU_PATH = os.getenv("AU_PATH", DEFAULT_AU_PATH).split(splitter)
  335. Carla.DEFAULT_CSOUND_PATH = os.getenv("CSOUND_PATH", DEFAULT_CSOUND_PATH).split(splitter)
  336. Carla.DEFAULT_GIG_PATH = os.getenv("GIG_PATH", DEFAULT_GIG_PATH).split(splitter)
  337. Carla.DEFAULT_SF2_PATH = os.getenv("SF2_PATH", DEFAULT_SF2_PATH).split(splitter)
  338. Carla.DEFAULT_SFZ_PATH = os.getenv("SFZ_PATH", DEFAULT_SFZ_PATH).split(splitter)
  339. else:
  340. Carla.DEFAULT_LADSPA_PATH = DEFAULT_LADSPA_PATH.split(splitter)
  341. Carla.DEFAULT_DSSI_PATH = DEFAULT_DSSI_PATH.split(splitter)
  342. Carla.DEFAULT_LV2_PATH = DEFAULT_LV2_PATH.split(splitter)
  343. Carla.DEFAULT_VST_PATH = DEFAULT_VST_PATH.split(splitter)
  344. Carla.DEFAULT_AU_PATH = DEFAULT_AU_PATH.split(splitter)
  345. Carla.DEFAULT_CSOUND_PATH = DEFAULT_CSOUND_PATH.split(splitter)
  346. Carla.DEFAULT_GIG_PATH = DEFAULT_GIG_PATH.split(splitter)
  347. Carla.DEFAULT_SF2_PATH = DEFAULT_SF2_PATH.split(splitter)
  348. Carla.DEFAULT_SFZ_PATH = DEFAULT_SFZ_PATH.split(splitter)
  349. # ------------------------------------------------------------------------------------------------------------
  350. # Search for Carla tools
  351. CWD = sys.path[0]
  352. # make it work with cxfreeze
  353. if CWD.endswith("/carla"):
  354. CWD = CWD.rsplit("/carla", 1)[0]
  355. elif CWD.endswith("\\carla.exe"):
  356. CWD = CWD.rsplit("\\carla.exe", 1)[0]
  357. # find tool
  358. def findTool(toolDir, toolName):
  359. if os.path.exists(os.path.join(CWD, toolDir, toolName)):
  360. return os.path.join(CWD, toolDir, toolName)
  361. for p in PATH:
  362. if os.path.exists(os.path.join(p, toolName)):
  363. return os.path.join(p, toolName)
  364. return ""
  365. # ------------------------------------------------------------------------------------------------------------
  366. # Init host
  367. def initHost(appName, libPrefix = None, failError = True):
  368. # -------------------------------------------------------------
  369. # Search for Carla library
  370. libname = "libcarla_"
  371. if Carla.isControl:
  372. libname += "control2"
  373. else:
  374. libname += "standalone2"
  375. if WINDOWS:
  376. libname += ".dll"
  377. elif MACOS:
  378. libname += ".dylib"
  379. else:
  380. libname += ".so"
  381. if libPrefix is not None:
  382. libfilename = os.path.join(libPrefix, "lib", "carla", libname)
  383. else:
  384. if os.path.exists(os.path.join(CWD, "backend", libname)):
  385. libfilename = os.path.join(CWD, "backend", libname)
  386. else:
  387. CARLA_LIB_PATH_env = os.getenv("CARLA_LIB_PATH")
  388. if CARLA_LIB_PATH_env and os.path.exists(CARLA_LIB_PATH_env):
  389. CARLA_LIB_PATH = (CARLA_LIB_PATH_env,)
  390. elif WINDOWS:
  391. CARLA_LIB_PATH = (os.path.join(PROGRAMFILES, "Carla"),)
  392. elif MACOS:
  393. CARLA_LIB_PATH = ("/opt/local/lib", "/usr/local/lib/", "/usr/lib")
  394. else:
  395. CARLA_LIB_PATH = ("/usr/local/lib/", "/usr/lib")
  396. del CARLA_LIB_PATH_env
  397. for path in CARLA_LIB_PATH:
  398. if os.path.exists(os.path.join(path, "carla", libname)):
  399. libfilename = os.path.join(path, "carla", libname)
  400. break
  401. else:
  402. libfilename = ""
  403. # -------------------------------------------------------------
  404. # Search for Carla tools
  405. carla_bridge_native = ""
  406. carla_bridge_posix32 = ""
  407. carla_bridge_posix64 = ""
  408. carla_bridge_win32 = ""
  409. carla_bridge_win64 = ""
  410. carla_bridge_lv2_external = ""
  411. carla_bridge_lv2_gtk2 = ""
  412. carla_bridge_lv2_gtk3 = ""
  413. carla_bridge_lv2_qt4 = ""
  414. carla_bridge_lv2_qt5 = ""
  415. carla_bridge_lv2_cocoa = ""
  416. carla_bridge_lv2_windows = ""
  417. carla_bridge_lv2_x11 = ""
  418. carla_bridge_vst_mac = ""
  419. carla_bridge_vst_hwnd = ""
  420. carla_bridge_vst_x11 = ""
  421. # -------------------------------------------------------------
  422. # find windows tools
  423. Carla.discovery_win32 = findTool("discovery", "carla-discovery-win32.exe")
  424. Carla.discovery_win64 = findTool("discovery", "carla-discovery-win64.exe")
  425. carla_bridge_win32 = findTool("bridges", "carla-bridge-win32.exe")
  426. carla_bridge_win64 = findTool("bridges", "carla-bridge-win64.exe")
  427. # -------------------------------------------------------------
  428. # find native and posix tools
  429. if not WINDOWS:
  430. Carla.discovery_native = findTool("discovery", "carla-discovery-native")
  431. Carla.discovery_posix32 = findTool("discovery", "carla-discovery-posix32")
  432. Carla.discovery_posix64 = findTool("discovery", "carla-discovery-posix64")
  433. carla_bridge_native = findTool("bridges", "carla-bridge-native")
  434. carla_bridge_posix32 = findTool("bridges", "carla-bridge-posix32")
  435. carla_bridge_posix64 = findTool("bridges", "carla-bridge-posix64")
  436. # -------------------------------------------------------------
  437. # find generic tools
  438. carla_bridge_lv2_external = findTool("bridges", "carla-bridge-lv2-external")
  439. # -------------------------------------------------------------
  440. # find windows only tools
  441. if WINDOWS:
  442. carla_bridge_lv2_windows = findTool("bridges", "carla-bridge-lv2-windows.exe")
  443. carla_bridge_vst_hwnd = findTool("bridges", "carla-bridge-vst-hwnd.exe")
  444. # -------------------------------------------------------------
  445. # find mac os only tools
  446. elif MACOS:
  447. carla_bridge_lv2_cocoa = findTool("bridges", "carla-bridge-lv2-cocoa")
  448. carla_bridge_vst_mac = findTool("bridges", "carla-bridge-vst-mac")
  449. # -------------------------------------------------------------
  450. # find other tools
  451. else:
  452. carla_bridge_lv2_gtk2 = findTool("bridges", "carla-bridge-lv2-gtk2")
  453. carla_bridge_lv2_gtk3 = findTool("bridges", "carla-bridge-lv2-gtk3")
  454. carla_bridge_lv2_qt4 = findTool("bridges", "carla-bridge-lv2-qt4")
  455. carla_bridge_lv2_qt5 = findTool("bridges", "carla-bridge-lv2-qt5")
  456. carla_bridge_lv2_x11 = findTool("bridges", "carla-bridge-lv2-x11")
  457. carla_bridge_vst_x11 = findTool("bridges", "carla-bridge-vst-x11")
  458. if not libfilename:
  459. if failError:
  460. QMessageBox.critical(None, "Error", "Failed to find the carla library, cannot continue")
  461. sys.exit(1)
  462. return
  463. # -------------------------------------------------------------
  464. # Init now
  465. Carla.host = Host(libfilename)
  466. # -------------------------------------------------------------
  467. # Set internal stuff
  468. Carla.host.set_engine_option(OPTION_PROCESS_NAME, 0, os.path.basename(appName))
  469. NSM_URL = os.getenv("NSM_URL")
  470. if NSM_URL:
  471. Carla.host.nsm_announce(NSM_URL, appName, os.getpid())
  472. # -------------------------------------------------------------
  473. # Set resource path
  474. localResources = os.path.join(libfilename.replace(libname, ""), "..", "modules", "carla_native", "resources")
  475. systemResources = os.path.join(libfilename.replace(libname, ""), "resources")
  476. if os.path.exists(localResources):
  477. Carla.host.set_engine_option(OPTION_PATH_RESOURCES, 0, localResources)
  478. elif os.path.exists(systemResources):
  479. Carla.host.set_engine_option(OPTION_PATH_RESOURCES, 0, systemResources)
  480. # -------------------------------------------------------------
  481. # Set bridge paths
  482. if carla_bridge_native:
  483. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_NATIVE, 0, carla_bridge_native)
  484. if carla_bridge_posix32:
  485. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_POSIX32, 0, carla_bridge_posix32)
  486. if carla_bridge_posix64:
  487. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_POSIX64, 0, carla_bridge_posix64)
  488. if carla_bridge_win32:
  489. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_WIN32, 0, carla_bridge_win32)
  490. if carla_bridge_win64:
  491. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_WIN64, 0, carla_bridge_win64)
  492. if carla_bridge_lv2_external:
  493. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_EXTERNAL, 0, carla_bridge_lv2_external)
  494. if WINDOWS:
  495. if carla_bridge_lv2_windows:
  496. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_WINDOWS, 0, carla_bridge_lv2_windows)
  497. if carla_bridge_vst_hwnd:
  498. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_VST_HWND, 0, carla_bridge_vst_hwnd)
  499. elif MACOS:
  500. if carla_bridge_lv2_cocoa:
  501. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_COCOA, 0, carla_bridge_lv2_cocoa)
  502. if carla_bridge_vst_mac:
  503. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_VST_MAC, 0, carla_bridge_vst_mac)
  504. else:
  505. if carla_bridge_lv2_gtk2:
  506. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_GTK2, 0, carla_bridge_lv2_gtk2)
  507. if carla_bridge_lv2_gtk3:
  508. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_GTK3, 0, carla_bridge_lv2_gtk3)
  509. if carla_bridge_lv2_qt4:
  510. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_QT4, 0, carla_bridge_lv2_qt4)
  511. if carla_bridge_lv2_qt5:
  512. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_QT5, 0, carla_bridge_lv2_qt5)
  513. if carla_bridge_lv2_x11:
  514. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_LV2_X11, 0, carla_bridge_lv2_x11)
  515. if carla_bridge_vst_x11:
  516. Carla.host.set_engine_option(OPTION_PATH_BRIDGE_VST_X11, 0, carla_bridge_vst_x11)
  517. # ------------------------------------------------------------------------------------------------------------
  518. # Check if a value is a number (float support)
  519. def isNumber(value):
  520. try:
  521. float(value)
  522. return True
  523. except:
  524. return False
  525. # ------------------------------------------------------------------------------------------------------------
  526. # Convert a value to a list
  527. def toList(value):
  528. if value is None:
  529. return []
  530. elif not isinstance(value, list):
  531. return [value]
  532. else:
  533. return value
  534. # ------------------------------------------------------------------------------------------------------------
  535. # Get Icon from user theme, using our own as backup (Oxygen)
  536. def getIcon(icon, size=16):
  537. return QIcon.fromTheme(icon, QIcon(":/%ix%i/%s.png" % (size, size, icon)))
  538. # ------------------------------------------------------------------------------------------------------------
  539. # Signal handler
  540. def signalHandler(sig, frame):
  541. if Carla.gui is None:
  542. return
  543. if sig in (SIGINT, SIGTERM):
  544. Carla.gui.SIGTERM.emit()
  545. elif haveSIGUSR1 and sig == SIGUSR1:
  546. Carla.gui.SIGUSR1.emit()
  547. def setUpSignals():
  548. signal(SIGINT, signalHandler)
  549. signal(SIGTERM, signalHandler)
  550. if not haveSIGUSR1:
  551. return
  552. signal(SIGUSR1, signalHandler)
  553. # ------------------------------------------------------------------------------------------------------------
  554. # QLineEdit and QPushButton combo
  555. def getAndSetPath(self_, currentPath, lineEdit):
  556. newPath = QFileDialog.getExistingDirectory(self_, self_.tr("Set Path"), currentPath, QFileDialog.ShowDirsOnly)
  557. if newPath:
  558. lineEdit.setText(newPath)
  559. return newPath
  560. # ------------------------------------------------------------------------------------------------------------
  561. # Custom MessageBox
  562. def CustomMessageBox(self_, icon, title, text, extraText="", buttons=QMessageBox.Yes|QMessageBox.No, defButton=QMessageBox.No):
  563. msgBox = QMessageBox(self_)
  564. msgBox.setIcon(icon)
  565. msgBox.setWindowTitle(title)
  566. msgBox.setText(text)
  567. msgBox.setInformativeText(extraText)
  568. msgBox.setStandardButtons(buttons)
  569. msgBox.setDefaultButton(defButton)
  570. return msgBox.exec_()