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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  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. # ------------------------------------------------------------------------------------------------------------