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

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