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

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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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_SF2:
  39. return "SF2"
  40. if ptype == PLUGIN_SFZ:
  41. return "SFZ"
  42. if ptype == PLUGIN_JACK:
  43. return "JACK"
  44. print("getPluginTypeAsString(%i) - invalid type" % ptype);
  45. return "Unknown"
  46. def getPluginTypeFromString(stype):
  47. if not stype:
  48. return PLUGIN_NONE
  49. stype = stype.lower()
  50. if stype == "none":
  51. return PLUGIN_NONE
  52. if stype in ("internal", "native"):
  53. return PLUGIN_INTERNAL
  54. if stype == "ladspa":
  55. return PLUGIN_LADSPA
  56. if stype == "dssi":
  57. return PLUGIN_DSSI
  58. if stype == "lv2":
  59. return PLUGIN_LV2
  60. if stype in ("vst2", "vst"):
  61. return PLUGIN_VST2
  62. if stype == "sf2":
  63. return PLUGIN_SF2
  64. if stype == "sfz":
  65. return PLUGIN_SFZ
  66. if stype == "jack":
  67. return PLUGIN_JACK
  68. print("getPluginTypeFromString(\"%s\") - invalid string type" % stype)
  69. return PLUGIN_NONE
  70. # ------------------------------------------------------------------------------------------------------------
  71. # Carla Utils API (C stuff)
  72. CarlaPipeClientHandle = c_void_p
  73. CarlaPipeCallbackFunc = CFUNCTYPE(None, c_void_p, c_char_p)
  74. # Information about an internal Carla plugin.
  75. # @see carla_get_cached_plugin_info()
  76. class CarlaCachedPluginInfo(Structure):
  77. _fields_ = [
  78. # Wherever the data in this struct is valid.
  79. # For performance reasons, plugins are only checked on request,
  80. # and as such, the count vs number of really valid plugins might not match.
  81. # Use this field to skip on plugins which cannot be loaded in Carla.
  82. ("valid", c_bool),
  83. # Plugin category.
  84. ("category", c_enum),
  85. # Plugin hints.
  86. # @see PluginHints
  87. ("hints", c_uint),
  88. # Number of audio inputs.
  89. ("audioIns", c_uint32),
  90. # Number of audio outputs.
  91. ("audioOuts", c_uint32),
  92. # Number of MIDI inputs.
  93. ("midiIns", c_uint32),
  94. # Number of MIDI outputs.
  95. ("midiOuts", c_uint32),
  96. # Number of input parameters.
  97. ("parameterIns", c_uint32),
  98. # Number of output parameters.
  99. ("parameterOuts", c_uint32),
  100. # Plugin name.
  101. ("name", c_char_p),
  102. # Plugin label.
  103. ("label", c_char_p),
  104. # Plugin author/maker.
  105. ("maker", c_char_p),
  106. # Plugin copyright/license.
  107. ("copyright", c_char_p)
  108. ]
  109. # ------------------------------------------------------------------------------------------------------------
  110. # Carla Utils API (Python compatible stuff)
  111. # @see CarlaCachedPluginInfo
  112. PyCarlaCachedPluginInfo = {
  113. 'valid': False,
  114. 'category': PLUGIN_CATEGORY_NONE,
  115. 'hints': 0x0,
  116. 'audioIns': 0,
  117. 'audioOuts': 0,
  118. 'midiIns': 0,
  119. 'midiOuts': 0,
  120. 'parameterIns': 0,
  121. 'parameterOuts': 0,
  122. 'name': "",
  123. 'label': "",
  124. 'maker': "",
  125. 'copyright': ""
  126. }
  127. # ------------------------------------------------------------------------------------------------------------
  128. # Carla Utils object using a DLL
  129. class CarlaUtils(object):
  130. def __init__(self, filename):
  131. object.__init__(self)
  132. self.lib = cdll.LoadLibrary(filename)
  133. #self.lib = CDLL(filename, RTLD_GLOBAL)
  134. self.lib.carla_get_complete_license_text.argtypes = None
  135. self.lib.carla_get_complete_license_text.restype = c_char_p
  136. self.lib.carla_get_supported_file_extensions.argtypes = None
  137. self.lib.carla_get_supported_file_extensions.restype = POINTER(c_char_p)
  138. self.lib.carla_get_supported_features.argtypes = None
  139. self.lib.carla_get_supported_features.restype = POINTER(c_char_p)
  140. self.lib.carla_get_cached_plugin_count.argtypes = [c_enum, c_char_p]
  141. self.lib.carla_get_cached_plugin_count.restype = c_uint
  142. self.lib.carla_get_cached_plugin_info.argtypes = [c_enum, c_uint]
  143. self.lib.carla_get_cached_plugin_info.restype = POINTER(CarlaCachedPluginInfo)
  144. self.lib.carla_fflush.argtypes = [c_bool]
  145. self.lib.carla_fflush.restype = None
  146. self.lib.carla_fputs.argtypes = [c_bool, c_char_p]
  147. self.lib.carla_fputs.restype = None
  148. self.lib.carla_set_process_name.argtypes = [c_char_p]
  149. self.lib.carla_set_process_name.restype = None
  150. self.lib.carla_pipe_client_new.argtypes = [POINTER(c_char_p), CarlaPipeCallbackFunc, c_void_p]
  151. self.lib.carla_pipe_client_new.restype = CarlaPipeClientHandle
  152. self.lib.carla_pipe_client_idle.argtypes = [CarlaPipeClientHandle]
  153. self.lib.carla_pipe_client_idle.restype = None
  154. self.lib.carla_pipe_client_is_running.argtypes = [CarlaPipeClientHandle]
  155. self.lib.carla_pipe_client_is_running.restype = c_bool
  156. self.lib.carla_pipe_client_lock.argtypes = [CarlaPipeClientHandle]
  157. self.lib.carla_pipe_client_lock.restype = None
  158. self.lib.carla_pipe_client_unlock.argtypes = [CarlaPipeClientHandle]
  159. self.lib.carla_pipe_client_unlock.restype = None
  160. self.lib.carla_pipe_client_readlineblock.argtypes = [CarlaPipeClientHandle, c_uint]
  161. self.lib.carla_pipe_client_readlineblock.restype = c_char_p
  162. self.lib.carla_pipe_client_write_msg.argtypes = [CarlaPipeClientHandle, c_char_p]
  163. self.lib.carla_pipe_client_write_msg.restype = c_bool
  164. self.lib.carla_pipe_client_write_and_fix_msg.argtypes = [CarlaPipeClientHandle, c_char_p]
  165. self.lib.carla_pipe_client_write_and_fix_msg.restype = c_bool
  166. self.lib.carla_pipe_client_flush.argtypes = [CarlaPipeClientHandle]
  167. self.lib.carla_pipe_client_flush.restype = c_bool
  168. self.lib.carla_pipe_client_flush_and_unlock.argtypes = [CarlaPipeClientHandle]
  169. self.lib.carla_pipe_client_flush_and_unlock.restype = c_bool
  170. self.lib.carla_pipe_client_destroy.argtypes = [CarlaPipeClientHandle]
  171. self.lib.carla_pipe_client_destroy.restype = None
  172. self.lib.carla_x11_reparent_window.argtypes = [c_uintptr, c_uintptr]
  173. self.lib.carla_x11_reparent_window.restype = None
  174. self.lib.carla_x11_move_window.argtypes = [c_uintptr, c_int, c_int]
  175. self.lib.carla_x11_move_window.restype = None
  176. self.lib.carla_x11_get_window_pos.argtypes = [c_uintptr]
  177. self.lib.carla_x11_get_window_pos.restype = POINTER(c_int)
  178. self.lib.carla_cocoa_get_window.argtypes = [c_uintptr]
  179. self.lib.carla_cocoa_get_window.restype = c_int
  180. # use _putenv on windows
  181. if not WINDOWS:
  182. self.msvcrt = None
  183. return
  184. self.msvcrt = cdll.msvcrt
  185. self.msvcrt._putenv.argtypes = [c_char_p]
  186. self.msvcrt._putenv.restype = None
  187. # --------------------------------------------------------------------------------------------------------
  188. # set environment variable
  189. def setenv(self, key, value):
  190. environ[key] = value
  191. if WINDOWS:
  192. keyvalue = "%s=%s" % (key, value)
  193. self.msvcrt._putenv(keyvalue.encode("utf-8"))
  194. # unset environment variable
  195. def unsetenv(self, key):
  196. if environ.get(key) is not None:
  197. environ.pop(key)
  198. if WINDOWS:
  199. keyrm = "%s=" % key
  200. self.msvcrt._putenv(keyrm.encode("utf-8"))
  201. # --------------------------------------------------------------------------------------------------------
  202. # Get the complete license text of used third-party code and features.
  203. # Returned string is in basic html format.
  204. def get_complete_license_text(self):
  205. return charPtrToString(self.lib.carla_get_complete_license_text())
  206. # Get the list of supported file extensions in carla_load_file().
  207. def get_supported_file_extensions(self):
  208. return charPtrPtrToStringList(self.lib.carla_get_supported_file_extensions())
  209. # Get the list of supported features in the current Carla build.
  210. def get_supported_features(self):
  211. return charPtrPtrToStringList(self.lib.carla_get_supported_features())
  212. # Get how many internal plugins are available.
  213. # Internal and LV2 plugin formats are cached and need to be discovered via this function.
  214. # Do not call this for any other plugin formats.
  215. def get_cached_plugin_count(self, ptype, pluginPath):
  216. return int(self.lib.carla_get_cached_plugin_count(ptype, pluginPath.encode("utf-8")))
  217. # Get information about a cached plugin.
  218. def get_cached_plugin_info(self, ptype, index):
  219. return structToDict(self.lib.carla_get_cached_plugin_info(ptype, index).contents)
  220. def fflush(self, err):
  221. self.lib.carla_fflush(err)
  222. def fputs(self, err, string):
  223. self.lib.carla_fputs(err, string.encode("utf-8"))
  224. def set_process_name(self, name):
  225. self.lib.carla_set_process_name(name.encode("utf-8"))
  226. def pipe_client_new(self, func):
  227. argc = len(argv)
  228. cagrvtype = c_char_p * argc
  229. cargv = cagrvtype()
  230. for i in range(argc):
  231. cargv[i] = c_char_p(argv[i].encode("utf-8"))
  232. self._pipeClientCallback = CarlaPipeCallbackFunc(func)
  233. return self.lib.carla_pipe_client_new(cargv, self._pipeClientCallback, None)
  234. def pipe_client_idle(self, handle):
  235. try:
  236. self.lib.carla_pipe_client_idle(handle)
  237. except OSError as e:
  238. print("pipe_client_idle", e)
  239. def pipe_client_is_running(self, handle):
  240. return bool(self.lib.carla_pipe_client_is_running(handle))
  241. def pipe_client_lock(self, handle):
  242. self.lib.carla_pipe_client_lock(handle)
  243. def pipe_client_unlock(self, handle):
  244. self.lib.carla_pipe_client_unlock(handle)
  245. def pipe_client_readlineblock(self, handle, timeout):
  246. return charPtrToString(self.lib.carla_pipe_client_readlineblock(handle, timeout))
  247. def pipe_client_write_msg(self, handle, msg):
  248. return bool(self.lib.carla_pipe_client_write_msg(handle, msg.encode("utf-8")))
  249. def pipe_client_write_and_fix_msg(self, handle, msg):
  250. return bool(self.lib.carla_pipe_client_write_and_fix_msg(handle, msg.encode("utf-8")))
  251. def pipe_client_flush(self, handle):
  252. return bool(self.lib.carla_pipe_client_flush(handle))
  253. def pipe_client_flush_and_unlock(self, handle):
  254. return bool(self.lib.carla_pipe_client_flush_and_unlock(handle))
  255. def pipe_client_destroy(self, handle):
  256. self.lib.carla_pipe_client_destroy(handle)
  257. def x11_reparent_window(self, winId1, winId2):
  258. self.lib.carla_x11_reparent_window(winId1, winId2)
  259. def x11_move_window(self, winId, x, y):
  260. self.lib.carla_x11_move_window(winId, x, y)
  261. def x11_get_window_pos(self, winId):
  262. data = self.lib.carla_x11_get_window_pos(winId)
  263. return tuple(int(data[i]) for i in range(4))
  264. def cocoa_get_window(self, winId):
  265. return self.lib.carla_cocoa_get_window(winId)
  266. # ------------------------------------------------------------------------------------------------------------