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_utils.py 17KB

10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla Backend utils
  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. # Imports (Global)
  19. from os import environ
  20. from sys import argv
  21. # ------------------------------------------------------------------------------------------------------------
  22. # Imports (ctypes)
  23. from ctypes import (
  24. c_bool, c_char_p, c_double, c_int, c_uint, c_uint32, c_void_p,
  25. cdll, Structure,
  26. CFUNCTYPE, POINTER
  27. )
  28. # ------------------------------------------------------------------------------------------------------------
  29. # Imports (Custom)
  30. from carla_backend import (
  31. PLUGIN_NONE,
  32. PLUGIN_INTERNAL,
  33. PLUGIN_LADSPA,
  34. PLUGIN_DSSI,
  35. PLUGIN_LV2,
  36. PLUGIN_VST2,
  37. PLUGIN_VST3,
  38. PLUGIN_AU,
  39. PLUGIN_JSFX,
  40. PLUGIN_DLS,
  41. PLUGIN_GIG,
  42. PLUGIN_SF2,
  43. PLUGIN_SFZ,
  44. PLUGIN_JACK,
  45. PLUGIN_JSFX,
  46. PLUGIN_CATEGORY_NONE,
  47. PLUGIN_CATEGORY_SYNTH,
  48. PLUGIN_CATEGORY_DELAY,
  49. PLUGIN_CATEGORY_EQ,
  50. PLUGIN_CATEGORY_FILTER,
  51. PLUGIN_CATEGORY_DISTORTION,
  52. PLUGIN_CATEGORY_DYNAMICS,
  53. PLUGIN_CATEGORY_MODULATOR,
  54. PLUGIN_CATEGORY_UTILITY,
  55. PLUGIN_CATEGORY_OTHER,
  56. WINDOWS,
  57. c_enum, c_uintptr,
  58. charPtrToString,
  59. charPtrPtrToStringList,
  60. structToDict
  61. )
  62. # ------------------------------------------------------------------------------------------------------------
  63. def getPluginTypeAsString(ptype):
  64. if ptype == PLUGIN_NONE:
  65. return "NONE"
  66. if ptype == PLUGIN_INTERNAL:
  67. return "Internal"
  68. if ptype == PLUGIN_LADSPA:
  69. return "LADSPA"
  70. if ptype == PLUGIN_DSSI:
  71. return "DSSI"
  72. if ptype == PLUGIN_LV2:
  73. return "LV2"
  74. if ptype == PLUGIN_VST2:
  75. return "VST2"
  76. if ptype == PLUGIN_VST3:
  77. return "VST3"
  78. if ptype == PLUGIN_AU:
  79. return "AU"
  80. if ptype == PLUGIN_JSFX:
  81. return "JSFX"
  82. if ptype == PLUGIN_DLS:
  83. return "DLS"
  84. if ptype == PLUGIN_GIG:
  85. return "GIG"
  86. if ptype == PLUGIN_SF2:
  87. return "SF2"
  88. if ptype == PLUGIN_SFZ:
  89. return "SFZ"
  90. if ptype == PLUGIN_JACK:
  91. return "JACK"
  92. if ptype == PLUGIN_JSFX:
  93. return "JSFX"
  94. print("getPluginTypeAsString(%i) - invalid type" % ptype)
  95. return "Unknown"
  96. def getPluginTypeFromString(stype):
  97. if not stype:
  98. return PLUGIN_NONE
  99. stype = stype.lower()
  100. if stype == "none":
  101. return PLUGIN_NONE
  102. if stype in ("internal", "native"):
  103. return PLUGIN_INTERNAL
  104. if stype == "ladspa":
  105. return PLUGIN_LADSPA
  106. if stype == "dssi":
  107. return PLUGIN_DSSI
  108. if stype == "lv2":
  109. return PLUGIN_LV2
  110. if stype in ("vst2", "vst"):
  111. return PLUGIN_VST2
  112. if stype == "vst3":
  113. return PLUGIN_VST3
  114. if stype in ("au", "audiounit"):
  115. return PLUGIN_AU
  116. if stype == "jsfx":
  117. return PLUGIN_JSFX
  118. if stype == "dls":
  119. return PLUGIN_DLS
  120. if stype == "gig":
  121. return PLUGIN_GIG
  122. if stype == "sf2":
  123. return PLUGIN_SF2
  124. if stype == "sfz":
  125. return PLUGIN_SFZ
  126. if stype == "jack":
  127. return PLUGIN_JACK
  128. if stype == "jsfx":
  129. return PLUGIN_JSFX
  130. print("getPluginTypeFromString(\"%s\") - invalid string type" % stype)
  131. return PLUGIN_NONE
  132. def getPluginCategoryAsString(category):
  133. if category == PLUGIN_CATEGORY_NONE:
  134. return "none"
  135. if category == PLUGIN_CATEGORY_SYNTH:
  136. return "synth"
  137. if category == PLUGIN_CATEGORY_DELAY:
  138. return "delay"
  139. if category == PLUGIN_CATEGORY_EQ:
  140. return "eq"
  141. if category == PLUGIN_CATEGORY_FILTER:
  142. return "filter"
  143. if category == PLUGIN_CATEGORY_DISTORTION:
  144. return "distortion"
  145. if category == PLUGIN_CATEGORY_DYNAMICS:
  146. return "dynamics"
  147. if category == PLUGIN_CATEGORY_MODULATOR:
  148. return "modulator"
  149. if category == PLUGIN_CATEGORY_UTILITY:
  150. return "utility"
  151. if category == PLUGIN_CATEGORY_OTHER:
  152. return "other"
  153. print("CarlaBackend::getPluginCategoryAsString(%i) - invalid category" % category)
  154. return "NONE"
  155. # ------------------------------------------------------------------------------------------------------------
  156. # Carla Utils API (C stuff)
  157. CarlaPipeClientHandle = c_void_p
  158. CarlaPipeCallbackFunc = CFUNCTYPE(None, c_void_p, c_char_p)
  159. # Information about an internal Carla plugin.
  160. # @see carla_get_cached_plugin_info()
  161. class CarlaCachedPluginInfo(Structure):
  162. _fields_ = [
  163. # Wherever the data in this struct is valid.
  164. # For performance reasons, plugins are only checked on request,
  165. # and as such, the count vs number of really valid plugins might not match.
  166. # Use this field to skip on plugins which cannot be loaded in Carla.
  167. ("valid", c_bool),
  168. # Plugin category.
  169. ("category", c_enum),
  170. # Plugin hints.
  171. # @see PluginHints
  172. ("hints", c_uint),
  173. # Number of audio inputs.
  174. ("audioIns", c_uint32),
  175. # Number of audio outputs.
  176. ("audioOuts", c_uint32),
  177. # Number of CV inputs.
  178. ("cvIns", c_uint32),
  179. # Number of CV outputs.
  180. ("cvOuts", c_uint32),
  181. # Number of MIDI inputs.
  182. ("midiIns", c_uint32),
  183. # Number of MIDI outputs.
  184. ("midiOuts", c_uint32),
  185. # Number of input parameters.
  186. ("parameterIns", c_uint32),
  187. # Number of output parameters.
  188. ("parameterOuts", c_uint32),
  189. # Plugin name.
  190. ("name", c_char_p),
  191. # Plugin label.
  192. ("label", c_char_p),
  193. # Plugin author/maker.
  194. ("maker", c_char_p),
  195. # Plugin copyright/license.
  196. ("copyright", c_char_p)
  197. ]
  198. # ------------------------------------------------------------------------------------------------------------
  199. # Carla Utils API (Python compatible stuff)
  200. # @see CarlaCachedPluginInfo
  201. PyCarlaCachedPluginInfo = {
  202. 'valid': False,
  203. 'category': PLUGIN_CATEGORY_NONE,
  204. 'hints': 0x0,
  205. 'audioIns': 0,
  206. 'audioOuts': 0,
  207. 'cvIns': 0,
  208. 'cvOuts': 0,
  209. 'midiIns': 0,
  210. 'midiOuts': 0,
  211. 'parameterIns': 0,
  212. 'parameterOuts': 0,
  213. 'name': "",
  214. 'label': "",
  215. 'maker': "",
  216. 'copyright': ""
  217. }
  218. # ------------------------------------------------------------------------------------------------------------
  219. # Carla Utils object using a DLL
  220. class CarlaUtils():
  221. def __init__(self, filename):
  222. self.lib = cdll.LoadLibrary(filename)
  223. #self.lib = CDLL(filename, RTLD_GLOBAL)
  224. self.lib.carla_get_complete_license_text.argtypes = None
  225. self.lib.carla_get_complete_license_text.restype = c_char_p
  226. self.lib.carla_get_juce_version.argtypes = None
  227. self.lib.carla_get_juce_version.restype = c_char_p
  228. self.lib.carla_get_supported_file_extensions.argtypes = None
  229. self.lib.carla_get_supported_file_extensions.restype = POINTER(c_char_p)
  230. self.lib.carla_get_supported_features.argtypes = None
  231. self.lib.carla_get_supported_features.restype = POINTER(c_char_p)
  232. self.lib.carla_get_cached_plugin_count.argtypes = [c_enum, c_char_p]
  233. self.lib.carla_get_cached_plugin_count.restype = c_uint
  234. self.lib.carla_get_cached_plugin_info.argtypes = [c_enum, c_uint]
  235. self.lib.carla_get_cached_plugin_info.restype = POINTER(CarlaCachedPluginInfo)
  236. self.lib.carla_fflush.argtypes = [c_bool]
  237. self.lib.carla_fflush.restype = None
  238. self.lib.carla_fputs.argtypes = [c_bool, c_char_p]
  239. self.lib.carla_fputs.restype = None
  240. self.lib.carla_set_process_name.argtypes = [c_char_p]
  241. self.lib.carla_set_process_name.restype = None
  242. self.lib.carla_pipe_client_new.argtypes = [POINTER(c_char_p), CarlaPipeCallbackFunc, c_void_p]
  243. self.lib.carla_pipe_client_new.restype = CarlaPipeClientHandle
  244. self.lib.carla_pipe_client_idle.argtypes = [CarlaPipeClientHandle]
  245. self.lib.carla_pipe_client_idle.restype = None
  246. self.lib.carla_pipe_client_is_running.argtypes = [CarlaPipeClientHandle]
  247. self.lib.carla_pipe_client_is_running.restype = c_bool
  248. self.lib.carla_pipe_client_lock.argtypes = [CarlaPipeClientHandle]
  249. self.lib.carla_pipe_client_lock.restype = None
  250. self.lib.carla_pipe_client_unlock.argtypes = [CarlaPipeClientHandle]
  251. self.lib.carla_pipe_client_unlock.restype = None
  252. self.lib.carla_pipe_client_readlineblock.argtypes = [CarlaPipeClientHandle, c_uint]
  253. self.lib.carla_pipe_client_readlineblock.restype = c_char_p
  254. self.lib.carla_pipe_client_readlineblock_bool.argtypes = [CarlaPipeClientHandle, c_uint]
  255. self.lib.carla_pipe_client_readlineblock_bool.restype = c_bool
  256. self.lib.carla_pipe_client_readlineblock_int.argtypes = [CarlaPipeClientHandle, c_uint]
  257. self.lib.carla_pipe_client_readlineblock_int.restype = c_int
  258. self.lib.carla_pipe_client_readlineblock_float.argtypes = [CarlaPipeClientHandle, c_uint]
  259. self.lib.carla_pipe_client_readlineblock_float.restype = c_double
  260. self.lib.carla_pipe_client_write_msg.argtypes = [CarlaPipeClientHandle, c_char_p]
  261. self.lib.carla_pipe_client_write_msg.restype = c_bool
  262. self.lib.carla_pipe_client_write_and_fix_msg.argtypes = [CarlaPipeClientHandle, c_char_p]
  263. self.lib.carla_pipe_client_write_and_fix_msg.restype = c_bool
  264. self.lib.carla_pipe_client_flush.argtypes = [CarlaPipeClientHandle]
  265. self.lib.carla_pipe_client_flush.restype = c_bool
  266. self.lib.carla_pipe_client_flush_and_unlock.argtypes = [CarlaPipeClientHandle]
  267. self.lib.carla_pipe_client_flush_and_unlock.restype = c_bool
  268. self.lib.carla_pipe_client_destroy.argtypes = [CarlaPipeClientHandle]
  269. self.lib.carla_pipe_client_destroy.restype = None
  270. self.lib.carla_juce_init.argtypes = None
  271. self.lib.carla_juce_init.restype = None
  272. self.lib.carla_juce_idle.argtypes = None
  273. self.lib.carla_juce_idle.restype = None
  274. self.lib.carla_juce_cleanup.argtypes = None
  275. self.lib.carla_juce_cleanup.restype = None
  276. self.lib.carla_get_desktop_scale_factor.argtypes = None
  277. self.lib.carla_get_desktop_scale_factor.restype = c_double
  278. self.lib.carla_cocoa_get_window.argtypes = [c_uintptr]
  279. self.lib.carla_cocoa_get_window.restype = c_int
  280. self.lib.carla_cocoa_set_transient_window_for.argtypes = [c_uintptr, c_uintptr]
  281. self.lib.carla_cocoa_set_transient_window_for.restype = None
  282. self.lib.carla_x11_reparent_window.argtypes = [c_uintptr, c_uintptr]
  283. self.lib.carla_x11_reparent_window.restype = None
  284. self.lib.carla_x11_move_window.argtypes = [c_uintptr, c_int, c_int]
  285. self.lib.carla_x11_move_window.restype = None
  286. self.lib.carla_x11_get_window_pos.argtypes = [c_uintptr]
  287. self.lib.carla_x11_get_window_pos.restype = POINTER(c_int)
  288. self._pipeClientFunc = None
  289. self._pipeClientCallback = None
  290. # use _putenv on windows
  291. if not WINDOWS:
  292. self.msvcrt = None
  293. return
  294. self.msvcrt = cdll.msvcrt
  295. # pylint: disable=protected-access
  296. self.msvcrt._putenv.argtypes = [c_char_p]
  297. self.msvcrt._putenv.restype = None
  298. # pylint: enable=protected-access
  299. # --------------------------------------------------------------------------------------------------------
  300. # set environment variable
  301. def setenv(self, key, value):
  302. environ[key] = value
  303. if WINDOWS:
  304. keyvalue = "%s=%s" % (key, value)
  305. # pylint: disable=protected-access
  306. self.msvcrt._putenv(keyvalue.encode("utf-8"))
  307. # pylint: enable=protected-access
  308. # unset environment variable
  309. def unsetenv(self, key):
  310. if environ.get(key) is not None:
  311. environ.pop(key)
  312. if WINDOWS:
  313. keyrm = "%s=" % key
  314. # pylint: disable=protected-access
  315. self.msvcrt._putenv(keyrm.encode("utf-8"))
  316. # pylint: enable=protected-access
  317. # --------------------------------------------------------------------------------------------------------
  318. # Get the complete license text of used third-party code and features.
  319. # Returned string is in basic html format.
  320. def get_complete_license_text(self):
  321. return charPtrToString(self.lib.carla_get_complete_license_text())
  322. # Get the juce version used in the current Carla build.
  323. def get_juce_version(self):
  324. return charPtrToString(self.lib.carla_get_juce_version())
  325. # Get the list of supported file extensions in carla_load_file().
  326. def get_supported_file_extensions(self):
  327. return charPtrPtrToStringList(self.lib.carla_get_supported_file_extensions())
  328. # Get the list of supported features in the current Carla build.
  329. def get_supported_features(self):
  330. return charPtrPtrToStringList(self.lib.carla_get_supported_features())
  331. # Get how many internal plugins are available.
  332. # Internal and LV2 plugin formats are cached and need to be discovered via this function.
  333. # Do not call this for any other plugin formats.
  334. def get_cached_plugin_count(self, ptype, pluginPath):
  335. return int(self.lib.carla_get_cached_plugin_count(ptype, pluginPath.encode("utf-8")))
  336. # Get information about a cached plugin.
  337. def get_cached_plugin_info(self, ptype, index):
  338. return structToDict(self.lib.carla_get_cached_plugin_info(ptype, index).contents)
  339. def fflush(self, err):
  340. self.lib.carla_fflush(err)
  341. def fputs(self, err, string):
  342. self.lib.carla_fputs(err, string.encode("utf-8"))
  343. def set_process_name(self, name):
  344. self.lib.carla_set_process_name(name.encode("utf-8"))
  345. def pipe_client_new(self, func):
  346. argc = len(argv)
  347. cagrvtype = c_char_p * argc
  348. cargv = cagrvtype()
  349. for i in range(argc):
  350. cargv[i] = c_char_p(argv[i].encode("utf-8"))
  351. self._pipeClientFunc = func
  352. self._pipeClientCallback = CarlaPipeCallbackFunc(func)
  353. return self.lib.carla_pipe_client_new(cargv, self._pipeClientCallback, None)
  354. def pipe_client_idle(self, handle):
  355. try:
  356. self.lib.carla_pipe_client_idle(handle)
  357. except OSError as e:
  358. print("carla_pipe_client_idle", e)
  359. def pipe_client_is_running(self, handle):
  360. return bool(self.lib.carla_pipe_client_is_running(handle))
  361. def pipe_client_lock(self, handle):
  362. self.lib.carla_pipe_client_lock(handle)
  363. def pipe_client_unlock(self, handle):
  364. self.lib.carla_pipe_client_unlock(handle)
  365. def pipe_client_readlineblock(self, handle, timeout):
  366. return charPtrToString(self.lib.carla_pipe_client_readlineblock(handle, timeout))
  367. def pipe_client_readlineblock_bool(self, handle, timeout):
  368. return bool(self.lib.carla_pipe_client_readlineblock_bool(handle, timeout))
  369. def pipe_client_readlineblock_int(self, handle, timeout):
  370. return int(self.lib.carla_pipe_client_readlineblock_int(handle, timeout))
  371. def pipe_client_readlineblock_float(self, handle, timeout):
  372. return float(self.lib.carla_pipe_client_readlineblock_float(handle, timeout))
  373. def pipe_client_write_msg(self, handle, msg):
  374. return bool(self.lib.carla_pipe_client_write_msg(handle, msg.encode("utf-8")))
  375. def pipe_client_write_and_fix_msg(self, handle, msg):
  376. return bool(self.lib.carla_pipe_client_write_and_fix_msg(handle, msg.encode("utf-8")))
  377. def pipe_client_flush(self, handle):
  378. return bool(self.lib.carla_pipe_client_flush(handle))
  379. def pipe_client_flush_and_unlock(self, handle):
  380. return bool(self.lib.carla_pipe_client_flush_and_unlock(handle))
  381. def pipe_client_destroy(self, handle):
  382. self.lib.carla_pipe_client_destroy(handle)
  383. def juce_init(self):
  384. self.lib.carla_juce_init()
  385. def juce_idle(self):
  386. self.lib.carla_juce_idle()
  387. def juce_cleanup(self):
  388. self.lib.carla_juce_cleanup()
  389. def get_desktop_scale_factor(self):
  390. return float(self.lib.carla_get_desktop_scale_factor())
  391. def cocoa_get_window(self, winId):
  392. return self.lib.carla_cocoa_get_window(winId)
  393. def cocoa_set_transient_window_for(self, childWinId, parentWinId):
  394. self.lib.carla_cocoa_set_transient_window_for(childWinId, parentWinId)
  395. def x11_reparent_window(self, winId1, winId2):
  396. self.lib.carla_x11_reparent_window(winId1, winId2)
  397. def x11_move_window(self, winId, x, y):
  398. self.lib.carla_x11_move_window(winId, x, y)
  399. def x11_get_window_pos(self, winId):
  400. data = self.lib.carla_x11_get_window_pos(winId)
  401. return tuple(int(data[i]) for i in range(4))
  402. # ------------------------------------------------------------------------------------------------------------