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.

824 lines
29KB

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