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.

448 lines
15KB

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