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 26KB

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
10 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
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
7 years ago
7 years ago
10 years ago
7 years ago
7 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Common Carla code
  4. # Copyright (C) 2011-2019 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. # Config
  19. # These will be modified during install
  20. X_LIBDIR_X = None
  21. X_DATADIR_X = None
  22. # ------------------------------------------------------------------------------------------------------------
  23. # Imports (Global)
  24. import os
  25. import sys
  26. from PyQt5.Qt import PYQT_VERSION_STR
  27. from PyQt5.QtCore import qFatal, QT_VERSION_STR, qWarning, QDir
  28. from PyQt5.QtGui import QIcon
  29. from PyQt5.QtWidgets import QFileDialog, QMessageBox
  30. # ------------------------------------------------------------------------------------------------------------
  31. # Import Signal
  32. from signal import signal, SIGINT, SIGTERM
  33. try:
  34. from signal import SIGUSR1
  35. haveSIGUSR1 = True
  36. except:
  37. haveSIGUSR1 = False
  38. # ------------------------------------------------------------------------------------------------------------
  39. # Imports (Custom)
  40. from carla_backend_qt import *
  41. # ------------------------------------------------------------------------------------------------------------
  42. # Platform specific stuff
  43. if WINDOWS:
  44. WINDIR = os.getenv("WINDIR")
  45. # ------------------------------------------------------------------------------------------------------------
  46. # Set Version
  47. VERSION = "2.0.90 (2.1-alpha2)"
  48. # ------------------------------------------------------------------------------------------------------------
  49. # Set TMP
  50. envTMP = os.getenv("TMP")
  51. if envTMP is None:
  52. if WINDOWS:
  53. qWarning("TMP variable not set")
  54. TMP = QDir.tempPath()
  55. else:
  56. TMP = envTMP
  57. if not os.path.exists(TMP):
  58. qWarning("TMP does not exist")
  59. TMP = "/"
  60. del envTMP
  61. # ------------------------------------------------------------------------------------------------------------
  62. # Set HOME
  63. envHOME = os.getenv("HOME")
  64. if envHOME is None:
  65. if LINUX or MACOS:
  66. qWarning("HOME variable not set")
  67. HOME = QDir.toNativeSeparators(QDir.homePath())
  68. else:
  69. HOME = envHOME
  70. if not os.path.exists(HOME):
  71. qWarning("HOME does not exist")
  72. HOME = TMP
  73. del envHOME
  74. # ------------------------------------------------------------------------------------------------------------
  75. # Set PATH
  76. envPATH = os.getenv("PATH")
  77. if envPATH is None:
  78. qWarning("PATH variable not set")
  79. if MACOS:
  80. PATH = ("/opt/local/bin", "/usr/local/bin", "/usr/bin", "/bin")
  81. elif WINDOWS:
  82. PATH = (os.path.join(WINDIR, "system32"), WINDIR)
  83. else:
  84. PATH = ("/usr/local/bin", "/usr/bin", "/bin")
  85. else:
  86. PATH = envPATH.split(os.pathsep)
  87. del envPATH
  88. # ------------------------------------------------------------------------------------------------------------
  89. # Static MIDI CC list
  90. MIDI_CC_LIST = (
  91. "0x01 Modulation",
  92. "0x02 Breath",
  93. "0x03 (Undefined)",
  94. "0x04 Foot",
  95. "0x05 Portamento",
  96. "0x07 Volume",
  97. "0x08 Balance",
  98. "0x09 (Undefined)",
  99. "0x0A Pan",
  100. "0x0B Expression",
  101. "0x0C FX Control 1",
  102. "0x0D FX Control 2",
  103. "0x0E (Undefined)",
  104. "0x0F (Undefined)",
  105. "0x10 General Purpose 1",
  106. "0x11 General Purpose 2",
  107. "0x12 General Purpose 3",
  108. "0x13 General Purpose 4",
  109. "0x14 (Undefined)",
  110. "0x15 (Undefined)",
  111. "0x16 (Undefined)",
  112. "0x17 (Undefined)",
  113. "0x18 (Undefined)",
  114. "0x19 (Undefined)",
  115. "0x1A (Undefined)",
  116. "0x1B (Undefined)",
  117. "0x1C (Undefined)",
  118. "0x1D (Undefined)",
  119. "0x1E (Undefined)",
  120. "0x1F (Undefined)",
  121. "0x46 Control 1 [Variation]",
  122. "0x47 Control 2 [Timbre]",
  123. "0x48 Control 3 [Release]",
  124. "0x49 Control 4 [Attack]",
  125. "0x4A Control 5 [Brightness]",
  126. "0x4B Control 6 [Decay]",
  127. "0x4C Control 7 [Vib Rate]",
  128. "0x4D Control 8 [Vib Depth]",
  129. "0x4E Control 9 [Vib Delay]",
  130. "0x4F Control 10 [Undefined]",
  131. "0x50 General Purpose 5",
  132. "0x51 General Purpose 6",
  133. "0x52 General Purpose 7",
  134. "0x53 General Purpose 8",
  135. "0x54 Portamento Control",
  136. "0x5B FX 1 Depth [Reverb]",
  137. "0x5C FX 2 Depth [Tremolo]",
  138. "0x5D FX 3 Depth [Chorus]",
  139. "0x5E FX 4 Depth [Detune]",
  140. "0x5F FX 5 Depth [Phaser]"
  141. )
  142. # ------------------------------------------------------------------------------------------------------------
  143. # PatchCanvas defines
  144. CANVAS_ANTIALIASING_SMALL = 1
  145. CANVAS_EYECANDY_SMALL = 1
  146. # ------------------------------------------------------------------------------------------------------------
  147. # Carla Settings keys
  148. CARLA_KEY_MAIN_PROJECT_FOLDER = "Main/ProjectFolder" # str
  149. CARLA_KEY_MAIN_USE_PRO_THEME = "Main/UseProTheme" # bool
  150. CARLA_KEY_MAIN_PRO_THEME_COLOR = "Main/ProThemeColor" # str
  151. CARLA_KEY_MAIN_REFRESH_INTERVAL = "Main/RefreshInterval" # int
  152. CARLA_KEY_MAIN_CONFIRM_EXIT = "Main/ConfirmExit" # bool
  153. CARLA_KEY_MAIN_SHOW_LOGS = "Main/ShowLogs" # bool
  154. CARLA_KEY_MAIN_EXPERIMENTAL = "Main/Experimental" # bool
  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_AUTO_SELECT_ITEMS = "Canvas/AutoSelectItems" # bool
  160. CARLA_KEY_CANVAS_EYE_CANDY = "Canvas/EyeCandy2" # bool
  161. CARLA_KEY_CANVAS_FANCY_EYE_CANDY = "Canvas/FancyEyeCandy" # bool
  162. CARLA_KEY_CANVAS_USE_OPENGL = "Canvas/UseOpenGL" # bool
  163. CARLA_KEY_CANVAS_ANTIALIASING = "Canvas/Antialiasing" # enum
  164. CARLA_KEY_CANVAS_HQ_ANTIALIASING = "Canvas/HQAntialiasing" # bool
  165. CARLA_KEY_ENGINE_DRIVER_PREFIX = "Engine/Driver-"
  166. CARLA_KEY_ENGINE_AUDIO_DRIVER = "Engine/AudioDriver" # str
  167. CARLA_KEY_ENGINE_PROCESS_MODE = "Engine/ProcessMode" # enum
  168. CARLA_KEY_ENGINE_TRANSPORT_MODE = "Engine/TransportMode" # enum
  169. CARLA_KEY_ENGINE_TRANSPORT_EXTRA = "Engine/TransportExtra" # str
  170. CARLA_KEY_ENGINE_FORCE_STEREO = "Engine/ForceStereo" # bool
  171. CARLA_KEY_ENGINE_PREFER_PLUGIN_BRIDGES = "Engine/PreferPluginBridges" # bool
  172. CARLA_KEY_ENGINE_PREFER_UI_BRIDGES = "Engine/PreferUiBridges" # bool
  173. CARLA_KEY_ENGINE_MANAGE_UIS = "Engine/ManageUIs" # bool
  174. CARLA_KEY_ENGINE_UIS_ALWAYS_ON_TOP = "Engine/UIsAlwaysOnTop" # bool
  175. CARLA_KEY_ENGINE_MAX_PARAMETERS = "Engine/MaxParameters" # int
  176. CARLA_KEY_ENGINE_UI_BRIDGES_TIMEOUT = "Engine/UiBridgesTimeout" # int
  177. CARLA_KEY_OSC_ENABLED = "OSC/Enabled"
  178. CARLA_KEY_OSC_TCP_PORT_ENABLED = "OSC/TCPEnabled"
  179. CARLA_KEY_OSC_TCP_PORT_NUMBER = "OSC/TCPNumber"
  180. CARLA_KEY_OSC_TCP_PORT_RANDOM = "OSC/TCPRandom"
  181. CARLA_KEY_OSC_UDP_PORT_ENABLED = "OSC/UDPEnabled"
  182. CARLA_KEY_OSC_UDP_PORT_NUMBER = "OSC/UDPNumber"
  183. CARLA_KEY_OSC_UDP_PORT_RANDOM = "OSC/UDPRandom"
  184. CARLA_KEY_PATHS_LADSPA = "Paths/LADSPA"
  185. CARLA_KEY_PATHS_DSSI = "Paths/DSSI"
  186. CARLA_KEY_PATHS_LV2 = "Paths/LV2"
  187. CARLA_KEY_PATHS_VST2 = "Paths/VST2"
  188. CARLA_KEY_PATHS_VST3 = "Paths/VST3"
  189. CARLA_KEY_PATHS_SF2 = "Paths/SF2"
  190. CARLA_KEY_PATHS_SFZ = "Paths/SFZ"
  191. CARLA_KEY_WINE_EXECUTABLE = "Wine/Executable" # str
  192. CARLA_KEY_WINE_AUTO_PREFIX = "Wine/AutoPrefix" # bool
  193. CARLA_KEY_WINE_FALLBACK_PREFIX = "Wine/FallbackPrefix" # str
  194. CARLA_KEY_WINE_RT_PRIO_ENABLED = "Wine/RtPrioEnabled" # bool
  195. CARLA_KEY_WINE_BASE_RT_PRIO = "Wine/BaseRtPrio" # int
  196. CARLA_KEY_WINE_SERVER_RT_PRIO = "Wine/ServerRtPrio" # int
  197. CARLA_KEY_EXPERIMENTAL_PLUGIN_BRIDGES = "Experimental/PluginBridges" # bool
  198. CARLA_KEY_EXPERIMENTAL_WINE_BRIDGES = "Experimental/WineBridges" # bool
  199. CARLA_KEY_EXPERIMENTAL_JACK_APPS = "Experimental/JackApplications" # bool
  200. CARLA_KEY_EXPERIMENTAL_EXPORT_LV2 = "Experimental/ExportLV2" # bool
  201. CARLA_KEY_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR = "Experimental/PreventBadBehaviour" # bool
  202. CARLA_KEY_EXPERIMENTAL_LOAD_LIB_GLOBAL = "Experimental/LoadLibGlobal" # bool
  203. # if pro theme is on and color is black
  204. CARLA_KEY_CUSTOM_PAINTING = "UseCustomPainting" # bool
  205. # ------------------------------------------------------------------------------------------------------------
  206. # Carla Settings defaults
  207. # Main
  208. CARLA_DEFAULT_MAIN_PROJECT_FOLDER = HOME
  209. CARLA_DEFAULT_MAIN_USE_PRO_THEME = True
  210. CARLA_DEFAULT_MAIN_PRO_THEME_COLOR = "Black"
  211. CARLA_DEFAULT_MAIN_REFRESH_INTERVAL = 20
  212. CARLA_DEFAULT_MAIN_CONFIRM_EXIT = True
  213. CARLA_DEFAULT_MAIN_SHOW_LOGS = bool(not WINDOWS)
  214. CARLA_DEFAULT_MAIN_EXPERIMENTAL = False
  215. # Canvas
  216. CARLA_DEFAULT_CANVAS_THEME = "Modern Dark"
  217. CARLA_DEFAULT_CANVAS_SIZE = "3100x2400"
  218. CARLA_DEFAULT_CANVAS_SIZE_WIDTH = 3100
  219. CARLA_DEFAULT_CANVAS_SIZE_HEIGHT = 2400
  220. CARLA_DEFAULT_CANVAS_USE_BEZIER_LINES = True
  221. CARLA_DEFAULT_CANVAS_AUTO_HIDE_GROUPS = True
  222. CARLA_DEFAULT_CANVAS_AUTO_SELECT_ITEMS = False
  223. CARLA_DEFAULT_CANVAS_EYE_CANDY = True
  224. CARLA_DEFAULT_CANVAS_FANCY_EYE_CANDY = False
  225. CARLA_DEFAULT_CANVAS_USE_OPENGL = False
  226. CARLA_DEFAULT_CANVAS_ANTIALIASING = CANVAS_ANTIALIASING_SMALL
  227. CARLA_DEFAULT_CANVAS_HQ_ANTIALIASING = False
  228. # Engine
  229. CARLA_DEFAULT_FORCE_STEREO = False
  230. CARLA_DEFAULT_PREFER_PLUGIN_BRIDGES = False
  231. CARLA_DEFAULT_PREFER_UI_BRIDGES = True
  232. CARLA_DEFAULT_MANAGE_UIS = True
  233. CARLA_DEFAULT_UIS_ALWAYS_ON_TOP = False
  234. CARLA_DEFAULT_MAX_PARAMETERS = MAX_DEFAULT_PARAMETERS
  235. CARLA_DEFAULT_UI_BRIDGES_TIMEOUT = 4000
  236. CARLA_DEFAULT_AUDIO_BUFFER_SIZE = 512
  237. CARLA_DEFAULT_AUDIO_SAMPLE_RATE = 44100
  238. CARLA_DEFAULT_AUDIO_TRIPLE_BUFFER = False
  239. if WINDOWS:
  240. CARLA_DEFAULT_AUDIO_DRIVER = "DirectSound"
  241. elif MACOS:
  242. CARLA_DEFAULT_AUDIO_DRIVER = "CoreAudio"
  243. else:
  244. CARLA_DEFAULT_AUDIO_DRIVER = "JACK"
  245. if LINUX:
  246. CARLA_DEFAULT_PROCESS_MODE = ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
  247. CARLA_DEFAULT_TRANSPORT_MODE = ENGINE_TRANSPORT_MODE_JACK
  248. else:
  249. CARLA_DEFAULT_PROCESS_MODE = ENGINE_PROCESS_MODE_PATCHBAY
  250. CARLA_DEFAULT_TRANSPORT_MODE = ENGINE_TRANSPORT_MODE_INTERNAL
  251. # OSC
  252. CARLA_DEFAULT_OSC_ENABLED = not WINDOWS
  253. CARLA_DEFAULT_OSC_TCP_PORT_ENABLED = True
  254. CARLA_DEFAULT_OSC_TCP_PORT_NUMBER = 22752
  255. CARLA_DEFAULT_OSC_TCP_PORT_RANDOM = False
  256. CARLA_DEFAULT_OSC_UDP_PORT_ENABLED = True
  257. CARLA_DEFAULT_OSC_UDP_PORT_NUMBER = 22752
  258. CARLA_DEFAULT_OSC_UDP_PORT_RANDOM = False
  259. # Wine
  260. CARLA_DEFAULT_WINE_EXECUTABLE = "wine"
  261. CARLA_DEFAULT_WINE_AUTO_PREFIX = True
  262. CARLA_DEFAULT_WINE_FALLBACK_PREFIX = os.path.expanduser("~/.wine")
  263. CARLA_DEFAULT_WINE_RT_PRIO_ENABLED = True
  264. CARLA_DEFAULT_WINE_BASE_RT_PRIO = 15
  265. CARLA_DEFAULT_WINE_SERVER_RT_PRIO = 10
  266. # Experimental
  267. CARLA_DEFAULT_EXPERIMENTAL_PLUGIN_BRIDGES = False
  268. CARLA_DEFAULT_EXPERIMENTAL_WINE_BRIDGES = False
  269. CARLA_DEFAULT_EXPERIMENTAL_JACK_APPS = False
  270. CARLA_DEFAULT_EXPERIMENTAL_LV2_EXPORT = False
  271. CARLA_DEFAULT_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR = False
  272. CARLA_DEFAULT_EXPERIMENTAL_LOAD_LIB_GLOBAL = False
  273. # ------------------------------------------------------------------------------------------------------------
  274. # Default Plugin Folders (get)
  275. DEFAULT_LADSPA_PATH = ""
  276. DEFAULT_DSSI_PATH = ""
  277. DEFAULT_LV2_PATH = ""
  278. DEFAULT_VST2_PATH = ""
  279. DEFAULT_VST3_PATH = ""
  280. DEFAULT_SF2_PATH = ""
  281. DEFAULT_SFZ_PATH = ""
  282. if WINDOWS:
  283. splitter = ";"
  284. APPDATA = os.getenv("APPDATA")
  285. PROGRAMFILES = os.getenv("PROGRAMFILES")
  286. PROGRAMFILESx86 = os.getenv("PROGRAMFILES(x86)")
  287. COMMONPROGRAMFILES = os.getenv("COMMONPROGRAMFILES")
  288. COMMONPROGRAMFILESx86 = os.getenv("COMMONPROGRAMFILES(x86)")
  289. # Small integrity tests
  290. if not APPDATA:
  291. qFatal("APPDATA variable not set, cannot continue")
  292. sys.exit(1)
  293. if not PROGRAMFILES:
  294. qFatal("PROGRAMFILES variable not set, cannot continue")
  295. sys.exit(1)
  296. if not COMMONPROGRAMFILES:
  297. qFatal("COMMONPROGRAMFILES variable not set, cannot continue")
  298. sys.exit(1)
  299. DEFAULT_LADSPA_PATH = APPDATA + "\\LADSPA"
  300. DEFAULT_LADSPA_PATH += ";" + PROGRAMFILES + "\\LADSPA"
  301. DEFAULT_DSSI_PATH = APPDATA + "\\DSSI"
  302. DEFAULT_DSSI_PATH += ";" + PROGRAMFILES + "\\DSSI"
  303. DEFAULT_LV2_PATH = APPDATA + "\\LV2"
  304. DEFAULT_LV2_PATH += ";" + COMMONPROGRAMFILES + "\\LV2"
  305. DEFAULT_VST2_PATH = PROGRAMFILES + "\\VstPlugins"
  306. DEFAULT_VST2_PATH += ";" + PROGRAMFILES + "\\Steinberg\\VstPlugins"
  307. if kIs64bit:
  308. DEFAULT_VST2_PATH += ";" + COMMONPROGRAMFILES + "\\VST2"
  309. DEFAULT_VST3_PATH = COMMONPROGRAMFILES + "\\VST3"
  310. DEFAULT_SF2_PATH = APPDATA + "\\SF2"
  311. DEFAULT_SFZ_PATH = APPDATA + "\\SFZ"
  312. if PROGRAMFILESx86:
  313. DEFAULT_LADSPA_PATH += ";" + PROGRAMFILESx86 + "\\LADSPA"
  314. DEFAULT_DSSI_PATH += ";" + PROGRAMFILESx86 + "\\DSSI"
  315. DEFAULT_VST2_PATH += ";" + PROGRAMFILESx86 + "\\VstPlugins"
  316. DEFAULT_VST2_PATH += ";" + PROGRAMFILESx86 + "\\Steinberg\\VstPlugins"
  317. if COMMONPROGRAMFILESx86:
  318. DEFAULT_VST3_PATH += COMMONPROGRAMFILESx86 + "\\VST3"
  319. elif HAIKU:
  320. splitter = ":"
  321. DEFAULT_LADSPA_PATH = HOME + "/.ladspa"
  322. DEFAULT_LADSPA_PATH += ":/boot/common/add-ons/ladspa"
  323. DEFAULT_DSSI_PATH = HOME + "/.dssi"
  324. DEFAULT_DSSI_PATH += ":/boot/common/add-ons/dssi"
  325. DEFAULT_LV2_PATH = HOME + "/.lv2"
  326. DEFAULT_LV2_PATH += ":/boot/common/add-ons/lv2"
  327. DEFAULT_VST2_PATH = HOME + "/.vst"
  328. DEFAULT_VST2_PATH += ":/boot/common/add-ons/vst"
  329. DEFAULT_VST3_PATH = HOME + "/.vst3"
  330. DEFAULT_VST3_PATH += ":/boot/common/add-ons/vst3"
  331. elif MACOS:
  332. splitter = ":"
  333. DEFAULT_LADSPA_PATH = HOME + "/Library/Audio/Plug-Ins/LADSPA"
  334. DEFAULT_LADSPA_PATH += ":/Library/Audio/Plug-Ins/LADSPA"
  335. DEFAULT_DSSI_PATH = HOME + "/Library/Audio/Plug-Ins/DSSI"
  336. DEFAULT_DSSI_PATH += ":/Library/Audio/Plug-Ins/DSSI"
  337. DEFAULT_LV2_PATH = HOME + "/Library/Audio/Plug-Ins/LV2"
  338. DEFAULT_LV2_PATH += ":/Library/Audio/Plug-Ins/LV2"
  339. DEFAULT_VST2_PATH = HOME + "/Library/Audio/Plug-Ins/VST"
  340. DEFAULT_VST2_PATH += ":/Library/Audio/Plug-Ins/VST"
  341. DEFAULT_VST3_PATH = HOME + "/Library/Audio/Plug-Ins/VST3"
  342. DEFAULT_VST3_PATH += ":/Library/Audio/Plug-Ins/VST3"
  343. else:
  344. splitter = ":"
  345. DEFAULT_LADSPA_PATH = HOME + "/.ladspa"
  346. DEFAULT_LADSPA_PATH += ":/usr/lib/ladspa"
  347. DEFAULT_LADSPA_PATH += ":/usr/local/lib/ladspa"
  348. DEFAULT_DSSI_PATH = HOME + "/.dssi"
  349. DEFAULT_DSSI_PATH += ":/usr/lib/dssi"
  350. DEFAULT_DSSI_PATH += ":/usr/local/lib/dssi"
  351. DEFAULT_LV2_PATH = HOME + "/.lv2"
  352. DEFAULT_LV2_PATH += ":/usr/lib/lv2"
  353. DEFAULT_LV2_PATH += ":/usr/local/lib/lv2"
  354. DEFAULT_VST2_PATH = HOME + "/.vst"
  355. DEFAULT_VST2_PATH += ":/usr/lib/vst"
  356. DEFAULT_VST2_PATH += ":/usr/local/lib/vst"
  357. DEFAULT_VST3_PATH = HOME + "/.vst3"
  358. DEFAULT_VST3_PATH += ":/usr/lib/vst3"
  359. DEFAULT_VST3_PATH += ":/usr/local/lib/vst3"
  360. DEFAULT_SF2_PATH = HOME + "/.sounds/sf2"
  361. DEFAULT_SF2_PATH += ":/usr/share/sounds/sf2"
  362. DEFAULT_SFZ_PATH = HOME + "/.sounds/sfz"
  363. DEFAULT_SFZ_PATH += ":/usr/share/sounds/sfz"
  364. if not WINDOWS:
  365. winePrefix = os.getenv("WINEPREFIX")
  366. if not winePrefix:
  367. winePrefix = HOME + "/.wine"
  368. if os.path.exists(winePrefix):
  369. DEFAULT_VST2_PATH += ":" + winePrefix + "/drive_c/Program Files/VstPlugins"
  370. DEFAULT_VST3_PATH += ":" + winePrefix + "/drive_c/Program Files/Common Files/VST3"
  371. if kIs64bit and os.path.exists(winePrefix + "/drive_c/Program Files (x86)"):
  372. DEFAULT_VST2_PATH += ":" + winePrefix + "/drive_c/Program Files (x86)/VstPlugins"
  373. DEFAULT_VST3_PATH += ":" + winePrefix + "/drive_c/Program Files (x86)/Common Files/VST3"
  374. del winePrefix
  375. # ------------------------------------------------------------------------------------------------------------
  376. # Default Plugin Folders (set)
  377. readEnvVars = True
  378. if WINDOWS:
  379. # Check if running Wine. If yes, ignore env vars
  380. from winreg import ConnectRegistry, OpenKey, CloseKey, HKEY_CURRENT_USER
  381. reg = ConnectRegistry(None, HKEY_CURRENT_USER)
  382. try:
  383. key = OpenKey(reg, r"SOFTWARE\Wine")
  384. CloseKey(key)
  385. del key
  386. readEnvVars = False
  387. except:
  388. pass
  389. CloseKey(reg)
  390. del reg
  391. if readEnvVars:
  392. CARLA_DEFAULT_LADSPA_PATH = os.getenv("LADSPA_PATH", DEFAULT_LADSPA_PATH).split(splitter)
  393. CARLA_DEFAULT_DSSI_PATH = os.getenv("DSSI_PATH", DEFAULT_DSSI_PATH).split(splitter)
  394. CARLA_DEFAULT_LV2_PATH = os.getenv("LV2_PATH", DEFAULT_LV2_PATH).split(splitter)
  395. CARLA_DEFAULT_VST2_PATH = os.getenv("VST_PATH", DEFAULT_VST2_PATH).split(splitter)
  396. CARLA_DEFAULT_VST3_PATH = os.getenv("VST3_PATH", DEFAULT_VST3_PATH).split(splitter)
  397. CARLA_DEFAULT_SF2_PATH = os.getenv("SF2_PATH", DEFAULT_SF2_PATH).split(splitter)
  398. CARLA_DEFAULT_SFZ_PATH = os.getenv("SFZ_PATH", DEFAULT_SFZ_PATH).split(splitter)
  399. else:
  400. CARLA_DEFAULT_LADSPA_PATH = DEFAULT_LADSPA_PATH.split(splitter)
  401. CARLA_DEFAULT_DSSI_PATH = DEFAULT_DSSI_PATH.split(splitter)
  402. CARLA_DEFAULT_LV2_PATH = DEFAULT_LV2_PATH.split(splitter)
  403. CARLA_DEFAULT_VST2_PATH = DEFAULT_VST2_PATH.split(splitter)
  404. CARLA_DEFAULT_VST3_PATH = DEFAULT_VST3_PATH.split(splitter)
  405. CARLA_DEFAULT_SF2_PATH = DEFAULT_SF2_PATH.split(splitter)
  406. CARLA_DEFAULT_SFZ_PATH = DEFAULT_SFZ_PATH.split(splitter)
  407. # ------------------------------------------------------------------------------------------------------------
  408. # Default Plugin Folders (cleanup)
  409. del DEFAULT_LADSPA_PATH
  410. del DEFAULT_DSSI_PATH
  411. del DEFAULT_LV2_PATH
  412. del DEFAULT_VST2_PATH
  413. del DEFAULT_VST3_PATH
  414. del DEFAULT_SF2_PATH
  415. del DEFAULT_SFZ_PATH
  416. # ------------------------------------------------------------------------------------------------------------
  417. # Global Carla object
  418. class CarlaObject(object):
  419. __slots__ = [
  420. 'gui', # Host Window
  421. 'nogui', # Skip UI
  422. 'term', # Terminated by OS signal
  423. 'utils' # Utils object
  424. ]
  425. gCarla = CarlaObject()
  426. gCarla.gui = None
  427. gCarla.nogui = False
  428. gCarla.term = False
  429. gCarla.utils = None
  430. # ------------------------------------------------------------------------------------------------------------
  431. # Set CWD
  432. CWD = sys.path[0]
  433. if not CWD:
  434. CWD = os.path.dirname(sys.argv[0])
  435. # make it work with cxfreeze
  436. if os.path.isfile(CWD):
  437. CWD = os.path.dirname(CWD)
  438. CXFREEZE = True
  439. else:
  440. CXFREEZE = False
  441. # ------------------------------------------------------------------------------------------------------------
  442. # Set DLL_EXTENSION
  443. if WINDOWS:
  444. DLL_EXTENSION = "dll"
  445. elif MACOS:
  446. DLL_EXTENSION = "dylib"
  447. else:
  448. DLL_EXTENSION = "so"
  449. # ------------------------------------------------------------------------------------------------------------
  450. # Check if a value is a number (float support)
  451. def isNumber(value):
  452. try:
  453. float(value)
  454. return True
  455. except:
  456. return False
  457. # ------------------------------------------------------------------------------------------------------------
  458. # Convert a value to a list
  459. def toList(value):
  460. if value is None:
  461. return []
  462. elif not isinstance(value, list):
  463. return [value]
  464. else:
  465. return value
  466. # ------------------------------------------------------------------------------------------------------------
  467. # Get Icon from user theme, using our own as backup (Oxygen)
  468. def getIcon(icon, size = 16):
  469. return QIcon.fromTheme(icon, QIcon(":/%ix%i/%s.png" % (size, size, icon)))
  470. # ------------------------------------------------------------------------------------------------------------
  471. # Handle some basic command-line arguments shared between all carla variants
  472. def handleInitialCommandLineArguments(file):
  473. initName = os.path.basename(file) if (file is not None and os.path.dirname(file) in PATH) else sys.argv[0]
  474. libPrefix = None
  475. for arg in sys.argv[1:]:
  476. if arg.startswith("--with-appname="):
  477. initName = os.path.basename(arg.replace("--with-appname=", ""))
  478. elif arg.startswith("--with-libprefix="):
  479. libPrefix = arg.replace("--with-libprefix=", "")
  480. elif arg == "--gdb":
  481. pass
  482. elif arg in ("-n", "--n", "-no-gui", "--no-gui", "-nogui", "--nogui"):
  483. gCarla.nogui = True
  484. elif arg in ("-h", "--h", "-help", "--help"):
  485. print("Usage: %s [OPTION]... [FILE|URL]" % initName)
  486. print("")
  487. print(" where FILE can be a Carla project or preset file to be loaded, or URL if using Carla-Control")
  488. print("")
  489. print(" and OPTION can be one or more of the following:")
  490. print("")
  491. print(" --gdb \t Run Carla inside gdb.")
  492. print(" -n,--no-gui \t Run Carla headless, don't show UI.")
  493. print("")
  494. print(" -h,--help \t Print this help text and exit.")
  495. print(" -v,--version\t Print version information and exit.")
  496. print("")
  497. sys.exit(0)
  498. elif arg in ("-v", "--v", "-version", "--version"):
  499. pathBinaries, pathResources = getPaths(libPrefix)
  500. print("Using Carla version %s" % VERSION)
  501. print(" Python version: %s" % sys.version.split(" ",1)[0])
  502. print(" Qt version: %s" % QT_VERSION_STR)
  503. print(" PyQt version: %s" % PYQT_VERSION_STR)
  504. print(" Binary dir: %s" % pathBinaries)
  505. print(" Resources dir: %s" % pathResources)
  506. sys.exit(0)
  507. return (initName, libPrefix)
  508. # ------------------------------------------------------------------------------------------------------------
  509. # Get initial project file (as passed in the command-line parameters)
  510. def getInitialProjectFile(app, skipExistCheck = False):
  511. # FIXME - PyQt mishandles unicode characters, we'll use direct sys.argv for now
  512. # see https://riverbankcomputing.com/pipermail/pyqt/2015-January/035395.html
  513. #args = app.arguments()[1:]
  514. args = sys.argv[1:]
  515. for arg in args:
  516. if arg.startswith("--with-appname=") or arg.startswith("--with-libprefix=") or arg == "--gdb":
  517. continue
  518. if arg in ("-n", "--n", "-no-gui", "--no-gui", "-nogui", "--nogui"):
  519. continue
  520. arg = os.path.expanduser(arg)
  521. if skipExistCheck or os.path.exists(arg):
  522. return arg
  523. return None
  524. # ------------------------------------------------------------------------------------------------------------
  525. # Get paths (binaries, resources)
  526. def getPaths(libPrefix = None):
  527. CWDl = CWD.lower()
  528. # adjust for special distros
  529. libdir = os.path.basename(os.path.normpath(X_LIBDIR_X)) if X_LIBDIR_X else "lib"
  530. datadir = os.path.basename(os.path.normpath(X_DATADIR_X)) if X_DATADIR_X else "share"
  531. # standalone, installed system-wide linux
  532. if libPrefix is not None:
  533. pathBinaries = os.path.join(libPrefix, libdir, "carla")
  534. pathResources = os.path.join(libPrefix, datadir, "carla", "resources")
  535. # standalone, local source
  536. elif CWDl.endswith("frontend"):
  537. pathBinaries = os.path.abspath(os.path.join(CWD, "..", "..", "bin"))
  538. pathResources = os.path.join(pathBinaries, "resources")
  539. # plugin
  540. elif CWDl.endswith("resources"):
  541. # installed system-wide linux
  542. if CWDl.endswith("/share/carla/resources"):
  543. pathBinaries = os.path.abspath(os.path.join(CWD, "..", "..", "..", libdir, "carla"))
  544. pathResources = CWD
  545. # local source
  546. elif CWDl.endswith("native-plugins%sresources" % os.sep):
  547. pathBinaries = os.path.abspath(os.path.join(CWD, "..", "..", "..", "bin"))
  548. pathResources = CWD
  549. # other
  550. else:
  551. pathBinaries = os.path.abspath(os.path.join(CWD, ".."))
  552. pathResources = CWD
  553. # everything else
  554. else:
  555. pathBinaries = CWD
  556. pathResources = os.path.join(pathBinaries, "resources")
  557. return (pathBinaries, pathResources)
  558. # ------------------------------------------------------------------------------------------------------------
  559. # Signal handler
  560. # TODO move to carla_host.py or something
  561. def signalHandler(sig, frame):
  562. if sig in (SIGINT, SIGTERM):
  563. gCarla.term = True
  564. if gCarla.gui is not None:
  565. gCarla.gui.SIGTERM.emit()
  566. elif haveSIGUSR1 and sig == SIGUSR1:
  567. if gCarla.gui is not None:
  568. gCarla.gui.SIGUSR1.emit()
  569. def setUpSignals():
  570. signal(SIGINT, signalHandler)
  571. signal(SIGTERM, signalHandler)
  572. if not haveSIGUSR1:
  573. return
  574. signal(SIGUSR1, signalHandler)
  575. # ------------------------------------------------------------------------------------------------------------
  576. # QLineEdit and QPushButton combo
  577. def getAndSetPath(parent, lineEdit):
  578. newPath = QFileDialog.getExistingDirectory(parent, parent.tr("Set Path"), lineEdit.text(), QFileDialog.ShowDirsOnly)
  579. if newPath:
  580. lineEdit.setText(newPath)
  581. return newPath
  582. # ------------------------------------------------------------------------------------------------------------
  583. # Custom MessageBox
  584. class QMessageBoxWithBetterWidth(QMessageBox):
  585. def __init__(self, parent):
  586. QMessageBox.__init__(self, parent)
  587. def showEvent(self, event):
  588. fontMetrics = self.fontMetrics()
  589. lines = self.text().strip().split("\n") + self.informativeText().strip().split("\n")
  590. if len(lines) > 0:
  591. width = 0
  592. for line in lines:
  593. width = max(fontMetrics.width(line), width)
  594. self.layout().setColumnMinimumWidth(2, width + 12)
  595. QMessageBox.showEvent(self, event)
  596. def CustomMessageBox(parent, icon, title, text,
  597. extraText="",
  598. buttons=QMessageBox.Yes|QMessageBox.No,
  599. defButton=QMessageBox.No):
  600. msgBox = QMessageBoxWithBetterWidth(parent)
  601. msgBox.setIcon(icon)
  602. msgBox.setWindowTitle(title)
  603. msgBox.setText(text)
  604. msgBox.setInformativeText(extraText)
  605. msgBox.setStandardButtons(buttons)
  606. msgBox.setDefaultButton(defButton)
  607. return msgBox.exec_()
  608. # ------------------------------------------------------------------------------------------------------------