Collection of tools useful for audio production
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.

1127 lines
36KB

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Carla Backend code
  4. # Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com> FIXME
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # 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 COPYING file
  17. # Imports (Global)
  18. import os, sys
  19. from ctypes import *
  20. from copy import deepcopy
  21. from subprocess import getoutput
  22. # Imports (Custom)
  23. try:
  24. import ladspa_rdf
  25. haveRDF = True
  26. except:
  27. print("RDF Support not available (LADSPA-RDF and LV2 will be disabled)")
  28. haveRDF = False
  29. # Set Platform and Architecture
  30. is64bit = False
  31. LINUX = False
  32. MACOS = False
  33. WINDOWS = False
  34. if (sys.platform == "darwin"):
  35. MACOS = True
  36. elif (sys.platform.startswith("linux")):
  37. LINUX = True
  38. if (len(os.uname()) > 4 and os.uname()[4] in ('x86_64',)): #FIXME - need more checks
  39. is64bit = True
  40. elif (sys.platform.startswith("win")):
  41. WINDOWS = True
  42. if (sys.platform == "win64"):
  43. is64bit = True
  44. if (is64bit):
  45. c_intptr = c_int64
  46. else:
  47. c_intptr = c_int32
  48. # Get short filename from full filename (/a/b.c -> b.c)
  49. def getShortFileName(filename):
  50. short = filename
  51. if (os.sep in filename):
  52. short = filename.rsplit(os.sep, 1)[1]
  53. return short
  54. # Convert a ctypes struct into a dict
  55. def struct_to_dict(struct):
  56. return dict((attr, getattr(struct, attr)) for attr, value in struct._fields_)
  57. # ------------------------------------------------------------------------------------------------
  58. # Default Plugin Folders
  59. if (WINDOWS):
  60. splitter = ";"
  61. APPDATA = os.getenv("APPDATA")
  62. PROGRAMFILES = os.getenv("PROGRAMFILES")
  63. COMMONPROGRAMFILES = os.getenv("COMMONPROGRAMFILES")
  64. # Small integrity tests
  65. if not APPDATA:
  66. print("APPDATA variable not set, cannot continue")
  67. sys.exit(1)
  68. if not PROGRAMFILES:
  69. print("PROGRAMFILES variable not set, cannot continue")
  70. sys.exit(1)
  71. if not COMMONPROGRAMFILES:
  72. print("COMMONPROGRAMFILES variable not set, cannot continue")
  73. sys.exit(1)
  74. DEFAULT_LADSPA_PATH = [
  75. os.path.join(APPDATA, "LADSPA"),
  76. os.path.join(PROGRAMFILES, "LADSPA")
  77. ]
  78. DEFAULT_DSSI_PATH = [
  79. os.path.join(APPDATA, "DSSI"),
  80. os.path.join(PROGRAMFILES, "DSSI")
  81. ]
  82. DEFAULT_LV2_PATH = [
  83. os.path.join(APPDATA, "LV2"),
  84. os.path.join(COMMONPROGRAMFILES, "LV2")
  85. ]
  86. DEFAULT_VST_PATH = [
  87. os.path.join(PROGRAMFILES, "VstPlugins"),
  88. os.path.join(PROGRAMFILES, "Steinberg", "VstPlugins")
  89. ]
  90. DEFAULT_SF2_PATH = [
  91. os.path.join(APPDATA, "SF2")
  92. ]
  93. #if (is64bit):
  94. # TODO
  95. elif (MACOS):
  96. splitter = ":"
  97. HOME = os.getenv("HOME")
  98. # Small integrity tests
  99. if not HOME:
  100. print("HOME variable not set, cannot continue")
  101. sys.exit(1)
  102. DEFAULT_LADSPA_PATH = [
  103. os.path.join(HOME, "Library", "Audio", "Plug-Ins", "LADSPA"),
  104. os.path.join("/", "Library", "Audio", "Plug-Ins", "LADSPA")
  105. ]
  106. DEFAULT_DSSI_PATH = [
  107. os.path.join(HOME, "Library", "Audio", "Plug-Ins", "DSSI"),
  108. os.path.join("/", "Library", "Audio", "Plug-Ins", "DSSI")
  109. ]
  110. DEFAULT_LV2_PATH = [
  111. os.path.join(HOME, "Library", "Audio", "Plug-Ins", "LV2"),
  112. os.path.join("/", "Library", "Audio", "Plug-Ins", "LV2")
  113. ]
  114. DEFAULT_VST_PATH = [
  115. os.path.join(HOME, "Library", "Audio", "Plug-Ins", "VST"),
  116. os.path.join("/", "Library", "Audio", "Plug-Ins", "VST")
  117. ]
  118. DEFAULT_SF2_PATH = [
  119. # TODO
  120. ]
  121. else:
  122. splitter = ":"
  123. HOME = os.getenv("HOME")
  124. # Small integrity tests
  125. if not HOME:
  126. print("HOME variable not set, cannot continue")
  127. sys.exit(1)
  128. DEFAULT_LADSPA_PATH = [
  129. os.path.join(HOME, ".ladspa"),
  130. os.path.join("/", "usr", "lib", "ladspa"),
  131. os.path.join("/", "usr", "local", "lib", "ladspa")
  132. ]
  133. DEFAULT_DSSI_PATH = [
  134. os.path.join(HOME, ".dssi"),
  135. os.path.join("/", "usr", "lib", "dssi"),
  136. os.path.join("/", "usr", "local", "lib", "dssi")
  137. ]
  138. DEFAULT_LV2_PATH = [
  139. os.path.join(HOME, ".lv2"),
  140. os.path.join("/", "usr", "lib", "lv2"),
  141. os.path.join("/", "usr", "local", "lib", "lv2")
  142. ]
  143. DEFAULT_VST_PATH = [
  144. os.path.join(HOME, ".vst"),
  145. os.path.join("/", "usr", "lib", "vst"),
  146. os.path.join("/", "usr", "local", "lib", "vst")
  147. ]
  148. DEFAULT_SF2_PATH = [
  149. os.path.join(HOME, ".sf2"),
  150. os.path.join("/", "usr", "share", "sounds", "sf2")
  151. ]
  152. # ------------------------------------------------------------------------------------------------
  153. # Carla command-line tools
  154. carla_discovery_unix32 = ""
  155. carla_discovery_unix64 = ""
  156. carla_discovery_win32 = ""
  157. carla_discovery_win64 = ""
  158. #carla_bridge_lv2_gtk2 = ""
  159. #carla_bridge_lv2_qt4 = ""
  160. #carla_bridge_lv2_x11 = ""
  161. #carla_bridge_vst_qt4 = ""
  162. #carla_bridge_winvst = ""
  163. if (WINDOWS):
  164. PATH = (os.path.join(PROGRAMFILES, "Cadence", "carla"),)
  165. else:
  166. PATH_env = os.getenv("PATH")
  167. if (PATH_env != None):
  168. PATH = PATH_env.split(":")
  169. else:
  170. PATH = ("/usr/bin", "/usr/local/bin")
  171. CWD = sys.path[0]
  172. # discovery-unix32
  173. if (os.path.exists(os.path.join(CWD, "carla-discovery", "carla-discovery-unix32"))):
  174. carla_discovery_unix32 = os.path.join(CWD, "carla-discovery", "carla-discovery-unix32")
  175. else:
  176. for p in PATH:
  177. if (os.path.exists(os.path.join(p, "carla-discovery-unix32"))):
  178. carla_discovery_unix32 = os.path.join(p, "carla-discovery-unix32")
  179. break
  180. # discovery-unix64
  181. if (os.path.exists(os.path.join(CWD, "carla-discovery", "carla-discovery-unix64"))):
  182. carla_discovery_unix64 = os.path.join(CWD, "carla-discovery", "carla-discovery-unix64")
  183. else:
  184. for p in PATH:
  185. if (os.path.exists(os.path.join(p, "carla-discovery-unix64"))):
  186. carla_discovery_unix64 = os.path.join(p, "carla-discovery-unix64")
  187. break
  188. # discovery-win32
  189. if (os.path.exists(os.path.join(CWD, "carla-discovery", "carla-discovery-win32.exe"))):
  190. carla_discovery_win32 = os.path.join(CWD, "carla-discovery", "carla-discovery-win32.exe")
  191. else:
  192. for p in PATH:
  193. if (os.path.exists(os.path.join(p, "carla-discovery-wine32.exe"))):
  194. carla_discovery_win32 = os.path.join(p, "carla-discovery-win32.exe")
  195. break
  196. # discovery-win64
  197. if (os.path.exists(os.path.join(CWD, "carla-discovery", "carla-discovery-win64.exe"))):
  198. carla_discovery_win64 = os.path.join(CWD, "carla-discovery", "carla-discovery-win64.exe")
  199. else:
  200. for p in PATH:
  201. if (os.path.exists(os.path.join(p, "carla-discovery-win64.exe"))):
  202. carla_discovery_win64 = os.path.join(p, "carla-discovery-win64.exe")
  203. break
  204. ## lv2-gtk2
  205. #if (os.path.exists(os.path.join(CWD, "carla-bridges", "carla-bridge-lv2-gtk2"))):
  206. #carla_bridge_lv2_gtk2 = os.path.join(CWD, "carla-bridges", "carla-bridge-lv2-gtk2")
  207. #else:
  208. #for p in PATH:
  209. #if (os.path.exists(os.path.join(p, "carla-bridge-lv2-gtk2"))):
  210. #carla_bridge_lv2_gtk2 = os.path.join(p, "carla-bridge-lv2-gtk2")
  211. #break
  212. ## lv2-qt4
  213. #if (os.path.exists(os.path.join(CWD, "carla-bridges", "carla-bridge-lv2-qt4"))):
  214. #carla_bridge_lv2_qt4 = os.path.join(CWD, "carla-bridges", "carla-bridge-lv2-qt4")
  215. #else:
  216. #for p in PATH:
  217. #if (os.path.exists(os.path.join(p, "carla-bridge-lv2-qt4"))):
  218. #carla_bridge_lv2_qt4 = os.path.join(p, "carla-bridge-lv2-qt4")
  219. #break
  220. ## lv2-x11
  221. #if (os.path.exists(os.path.join(CWD, "carla-bridges", "carla-bridge-lv2-x11"))):
  222. #carla_bridge_lv2_x11 = os.path.join(CWD, "carla-bridges", "carla-bridge-lv2-x11")
  223. #else:
  224. #for p in PATH:
  225. #if (os.path.exists(os.path.join(p, "carla-bridge-lv2-x11"))):
  226. #carla_bridge_lv2_x11 = os.path.join(p, "carla-bridge-lv2-x11")
  227. #break
  228. ## vst-qt4
  229. #if (os.path.exists(os.path.join(CWD, "carla-bridges", "carla-bridge-vst-qt4"))):
  230. #carla_bridge_vst_qt4 = os.path.join(CWD, "carla-bridges", "carla-bridge-vst-qt4")
  231. #else:
  232. #for p in PATH:
  233. #if (os.path.exists(os.path.join(p, "carla-bridge-vst-qt4"))):
  234. #carla_bridge_vst_qt4 = os.path.join(p, "carla-bridge-vst-qt4")
  235. #break
  236. ## winvst
  237. #if (os.path.exists(os.path.join(CWD, "carla-bridges", "carla-bridge-winvst.exe"))):
  238. #carla_bridge_winvst = os.path.join(CWD, "carla-bridges", "carla-bridge-winvst.exe")
  239. #else:
  240. #for p in PATH:
  241. #if (os.path.exists(os.path.join(p, "carla-bridge-winvst.exe"))):
  242. #carla_bridge_winvst = os.path.join(p, "carla-bridge-winvst.exe")
  243. #break
  244. print("carla_discovery_unix32 ->", carla_discovery_unix32)
  245. print("carla_discovery_unix64 ->", carla_discovery_unix64)
  246. print("carla_discovery_win32 ->", carla_discovery_win32)
  247. print("carla_discovery_win64 ->", carla_discovery_win64)
  248. print("LADSPA ->", DEFAULT_LADSPA_PATH)
  249. print("DSSI ->", DEFAULT_DSSI_PATH)
  250. print("LV2 ->", DEFAULT_LV2_PATH)
  251. print("VST ->", DEFAULT_VST_PATH)
  252. print("SF2 ->", DEFAULT_SF2_PATH)
  253. # ------------------------------------------------------------------------------------------------
  254. # Plugin Query (helper functions)
  255. def findBinaries(PATH, OS):
  256. binaries = []
  257. if (OS == "WINDOWS"):
  258. extensions = (".dll", ".dlL", ".dLL", ".DLL", "DLl", "Dll")
  259. elif (OS == "MACOS"):
  260. extensions = (".dylib", ".so")
  261. else:
  262. extensions = (".so", ".sO", ".SO", ".So")
  263. for root, dirs, files in os.walk(PATH):
  264. for name in [name for name in files if name.endswith(extensions)]:
  265. binaries.append(os.path.join(root, name))
  266. return binaries
  267. def findSoundFonts(PATH):
  268. soundfonts = []
  269. extensions = (".sf2", ".sF2", ".SF2", ".Sf2")
  270. for root, dirs, files in os.walk(PATH):
  271. for name in [name for name in files if name.endswith(extensions)]:
  272. soundfonts.append(os.path.join(root, name))
  273. return soundfonts
  274. #def findLV2Bundles(PATH):
  275. #bundles = []
  276. #extensions = (".lv2", ".lV2", ".LV2", ".Lv2")
  277. #for root, dirs, files in os.walk(PATH):
  278. #for dir_ in [dir_ for dir_ in dirs if dir_.endswith(extensions)]:
  279. #bundles.append(os.path.join(root, dir_))
  280. #return bundles
  281. #def findDSSIGUI(filename, name, label):
  282. #gui_filename = ""
  283. #plugin_dir = filename.rsplit(".", 1)[0]
  284. #short_name = getShortFileName(filename).rsplit(".", 1)[0]
  285. #check_name = name.replace(" ","_")
  286. #check_label = label
  287. #check_sname = short_name
  288. #if (check_name[-1] != "_"): check_name += "_"
  289. #if (check_label[-1] != "_"): check_label += "_"
  290. #if (check_sname[-1] != "_"): check_sname += "_"
  291. #for root, dirs, files in os.walk(plugin_dir):
  292. #plugin_files = files
  293. #break
  294. #else:
  295. #plugin_files = []
  296. #for i in range(len(plugin_files)):
  297. #if (check_name in files[i] or check_label in files[i] or check_sname in files[i]):
  298. #gui_filename = os.path.join(plugin_dir, files[i])
  299. #break
  300. #return gui_filename
  301. # ------------------------------------------------------------------------------------------------
  302. # Plugin Query
  303. #PyPluginInfo = {
  304. #'type': 0,
  305. #'category': 0,
  306. #'hints': 0,
  307. #'binary': "",
  308. #'name': "",
  309. #'label': "",
  310. #'maker': "",
  311. #'copyright': "",
  312. #'id': "",
  313. #'audio.ins': 0,
  314. #'audio.outs': 0,
  315. #'audio.totals': 0,
  316. #'midi.ins': 0,
  317. #'midi.outs': 0,
  318. #'midi.totals': 0,
  319. #'parameters.ins': 0,
  320. #'parameters.outs': 0,
  321. #'parameters.total': 0,
  322. #'programs.total': 0
  323. #}
  324. def runCarlaDiscovery(itype, stype, filename, tool, isWine=False):
  325. short_name = getShortFileName(filename).rsplit(".", 1)[0]
  326. plugins = []
  327. pinfo = None
  328. command = ""
  329. if (LINUX or MACOS):
  330. command += "env LANG=C "
  331. if (isWine):
  332. command += "WINEDEBUG=-all "
  333. command += "%s %s \"%s\"" % (tool, stype, filename)
  334. print(command)
  335. try:
  336. output = getoutput(command).split("\n")
  337. except:
  338. output = []
  339. for line in output:
  340. print(line)
  341. #if (line == "carla-discovery::init::-----------"):
  342. #pinfo = deepcopy(PyPluginInfo)
  343. #pinfo['type'] = itype
  344. #pinfo['category'] = PLUGIN_CATEGORY_NONE
  345. #pinfo['hints'] = 0
  346. #pinfo['binary'] = filename
  347. #pinfo['name'] = ""
  348. #pinfo['label'] = ""
  349. #pinfo['maker'] = ""
  350. #pinfo['copyright'] = ""
  351. #pinfo['id'] = ""
  352. #pinfo['audio.ins'] = 0
  353. #pinfo['audio.outs'] = 0
  354. #pinfo['audio.total'] = 0
  355. #pinfo['midi.ins'] = 0
  356. #pinfo['midi.outs'] = 0
  357. #pinfo['midi.total'] = 0
  358. #pinfo['parameters.ins'] = 0
  359. #pinfo['parameters.outs'] = 0
  360. #pinfo['parameters.total'] = 0
  361. #pinfo['programs.total'] = 0
  362. #elif (line == "carla-discovery::end::------------"):
  363. #if (pinfo != None):
  364. #plugins.append(pinfo)
  365. #elif (line == "Segmentation fault"):
  366. #print "carla-discovery::crash::%s crashed during discovery" % (filename)
  367. #elif line.startswith("err:module:import_dll Library"):
  368. #print line
  369. #elif line.startswith("carla-discovery::error::"):
  370. #print line, "-", filename
  371. #elif line.startswith("carla-discovery::"):
  372. #if (pinfo == None): continue
  373. #prop, value = line.replace("carla-discovery::","").split("::", 1)
  374. #if (prop == "category"):
  375. #if value.isdigit():
  376. #pinfo['category'] = int(value)
  377. #elif (prop == "name"):
  378. #if (value):
  379. #pinfo['name'] = value
  380. #else:
  381. #pinfo['name'] = short_name
  382. #elif (prop == "label"):
  383. #if (value):
  384. #pinfo['label'] = value
  385. #else:
  386. #pinfo['label'] = short_name
  387. #elif (prop == "maker"):
  388. #pinfo['maker'] = value
  389. #elif (prop == "copyright"):
  390. #pinfo['copyright'] = value
  391. #elif (prop == "id"):
  392. #pinfo['id'] = value
  393. #elif (prop == "hints"):
  394. #if value.isdigit():
  395. #pinfo['hints'] = int(value)
  396. #elif (prop == "audio.ins"):
  397. #if value.isdigit():
  398. #pinfo['audio.ins'] = int(value)
  399. #elif (prop == "audio.outs"):
  400. #if value.isdigit():
  401. #pinfo['audio.outs'] = int(value)
  402. #elif (prop == "audio.total"):
  403. #if value.isdigit():
  404. #pinfo['audio.total'] = int(value)
  405. #elif (prop == "midi.ins"):
  406. #if value.isdigit():
  407. #pinfo['midi.ins'] = int(value)
  408. #elif (prop == "midi.outs"):
  409. #if value.isdigit():
  410. #pinfo['midi.outs'] = int(value)
  411. #elif (prop == "midi.total"):
  412. #if value.isdigit():
  413. #pinfo['midi.total'] = int(value)
  414. #elif (prop == "parameters.ins"):
  415. #if value.isdigit():
  416. #pinfo['parameters.ins'] = int(value)
  417. #elif (prop == "parameters.outs"):
  418. #if value.isdigit():
  419. #pinfo['parameters.outs'] = int(value)
  420. #elif (prop == "parameters.total"):
  421. #if value.isdigit():
  422. #pinfo['parameters.total'] = int(value)
  423. #elif (prop == "programs.total"):
  424. #if value.isdigit():
  425. #pinfo['programs.total'] = int(value)
  426. ## Additional checks
  427. #for pinfo in plugins:
  428. #if (itype == PLUGIN_LADSPA):
  429. ## TODO - find category using ladspa_rdf
  430. #pass
  431. #elif (itype == PLUGIN_DSSI):
  432. #if (findDSSIGUI(pinfo['binary'], pinfo['name'], pinfo['label'])):
  433. #pinfo['hints'] |= PLUGIN_HAS_GUI
  434. return plugins
  435. def checkPluginLADSPA(filename, tool, isWine=False):
  436. return runCarlaDiscovery(PLUGIN_LADSPA, "LADSPA", filename, tool, isWine)
  437. def checkPluginDSSI(filename, tool, isWine=False):
  438. return runCarlaDiscovery(PLUGIN_DSSI, "DSSI", filename, tool, isWine)
  439. def checkPluginVST(filename, tool, isWine=False):
  440. return runCarlaDiscovery(PLUGIN_VST, "VST", filename, tool, isWine)
  441. def checkPluginSF2(filename, tool):
  442. return runCarlaDiscovery(PLUGIN_SF2, "SF2", filename, tool)
  443. #def checkPluginLV2(rdf_info):
  444. #plugins = []
  445. #pinfo = deepcopy(PyPluginInfo)
  446. #pinfo['type'] = PLUGIN_LV2
  447. #pinfo['category'] = PLUGIN_CATEGORY_NONE # TODO
  448. #pinfo['hints'] = 0
  449. #pinfo['binary'] = rdf_info['Binary']
  450. #pinfo['name'] = rdf_info['Name']
  451. #pinfo['label'] = rdf_info['URI']
  452. #pinfo['maker'] = rdf_info['Author']
  453. #pinfo['copyright'] = rdf_info['License']
  454. #pinfo['id'] = str(rdf_info['UniqueID'])
  455. #pinfo['audio.ins'] = 0
  456. #pinfo['audio.outs'] = 0
  457. #pinfo['audio.total'] = 0
  458. #pinfo['midi.ins'] = 0
  459. #pinfo['midi.outs'] = 0
  460. #pinfo['midi.total'] = 0
  461. #pinfo['parameters.ins'] = 0
  462. #pinfo['parameters.outs'] = 0
  463. #pinfo['parameters.total'] = 0
  464. #pinfo['programs.total'] = rdf_info['PresetCount']
  465. #if (not rdf_info['Bundle'] or pinfo['binary'] == "" or pinfo['name'] == ""):
  466. #return None
  467. #for i in range(rdf_info['PortCount']):
  468. #PortType = rdf_info['Ports'][i]['Type']
  469. #PortProps = rdf_info['Ports'][i]['Properties']
  470. #if (PortType & lv2_rdf.LV2_PORT_AUDIO):
  471. #pinfo['audio.total'] += 1
  472. #if (PortType & lv2_rdf.LV2_PORT_INPUT):
  473. #pinfo['audio.ins'] += 1
  474. #elif (PortType & lv2_rdf.LV2_PORT_OUTPUT):
  475. #pinfo['audio.outs'] += 1
  476. #elif (PortType & lv2_rdf.LV2_PORT_EVENT_MIDI):
  477. #pinfo['midi.total'] += 1
  478. #if (PortType & lv2_rdf.LV2_PORT_INPUT):
  479. #pinfo['midi.ins'] += 1
  480. #elif (PortType & lv2_rdf.LV2_PORT_OUTPUT):
  481. #pinfo['midi.outs'] += 1
  482. #elif (PortType & lv2_rdf.LV2_PORT_CONTROL):
  483. #pinfo['parameters.total'] += 1
  484. #if (PortType & lv2_rdf.LV2_PORT_INPUT):
  485. #pinfo['parameters.ins'] += 1
  486. #elif (PortType & lv2_rdf.LV2_PORT_OUTPUT):
  487. #if (not PortProps & lv2_rdf.LV2_PORT_LATENCY):
  488. #pinfo['parameters.outs'] += 1
  489. #if (rdf_info['Type'] & lv2_rdf.LV2_GROUP_GENERATOR):
  490. #pinfo['hints'] |= PLUGIN_IS_SYNTH
  491. #if (rdf_info['UICount'] > 0):
  492. #pinfo['hints'] |= PLUGIN_HAS_GUI
  493. #plugins.append(pinfo)
  494. #return plugins
  495. # ------------------------------------------------------------------------------------------------
  496. # Backend C++ -> Python variables
  497. global Callback
  498. c_enum = c_int
  499. c_nullptr = None
  500. # static max values
  501. MAX_PLUGINS = 99
  502. MAX_PARAMETERS = 200
  503. MAX_MIDI_EVENTS = 512
  504. # plugin hints
  505. PLUGIN_HAS_GUI = 0x01
  506. PLUGIN_IS_BRIDGE = 0x02
  507. PLUGIN_IS_SYNTH = 0x04
  508. PLUGIN_USES_CHUNKS = 0x08
  509. PLUGIN_CAN_DRYWET = 0x10
  510. PLUGIN_CAN_VOL = 0x20
  511. PLUGIN_CAN_BALANCE = 0x40
  512. # parameter hints
  513. PARAMETER_IS_ENABLED = 0x01
  514. PARAMETER_IS_AUTOMABLE = 0x02
  515. PARAMETER_HAS_STRICT_BOUNDS = 0x04
  516. PARAMETER_USES_SCALEPOINTS = 0x08
  517. PARAMETER_USES_SAMPLERATE = 0x10
  518. # enum PluginType
  519. PLUGIN_NONE = 0
  520. PLUGIN_LADSPA = 1
  521. PLUGIN_DSSI = 2
  522. PLUGIN_LV2 = 3
  523. PLUGIN_VST = 4
  524. PLUGIN_WINVST = 5
  525. PLUGIN_SF2 = 6
  526. # enum PluginCategory
  527. PLUGIN_CATEGORY_NONE = 0
  528. PLUGIN_CATEGORY_SYNTH = 1
  529. PLUGIN_CATEGORY_DELAY = 2 # also Reverb
  530. PLUGIN_CATEGORY_EQ = 3
  531. PLUGIN_CATEGORY_FILTER = 4
  532. PLUGIN_CATEGORY_DYNAMICS = 5 # Amplifier, Compressor, Gate
  533. PLUGIN_CATEGORY_MODULATOR = 6 # Chorus, Flanger, Phaser
  534. PLUGIN_CATEGORY_UTILITY = 7 # Analyzer, Converter, Mixer
  535. PLUGIN_CATEGORY_OUTRO = 8 # used to check if a plugin has a category
  536. # enum ParameterType
  537. PARAMETER_UNKNOWN = 0
  538. PARAMETER_INPUT = 1
  539. PARAMETER_OUTPUT = 2
  540. # enum InternalParametersIndex
  541. PARAMETER_ACTIVE = -1
  542. PARAMETER_DRYWET = -2
  543. PARAMETER_VOLUME = -3
  544. PARAMETER_BALANCE_LEFT = -4
  545. PARAMETER_BALANCE_RIGHT = -5
  546. # enum CustomDataType
  547. CUSTOM_DATA_INVALID = 0
  548. CUSTOM_DATA_STRING = 1
  549. CUSTOM_DATA_BINARY = 2
  550. # enum GuiType
  551. GUI_NONE = 0
  552. GUI_INTERNAL_QT4 = 1
  553. GUI_INTERNAL_X11 = 2
  554. GUI_EXTERNAL_OSC = 3
  555. GUI_EXTERNAL_LV2 = 4
  556. # enum OptionsType
  557. OPTION_GLOBAL_JACK_CLIENT = 1
  558. OPTION_BRIDGE_PATH_LV2_GTK2 = 2
  559. OPTION_BRIDGE_PATH_LV2_QT4 = 3
  560. OPTION_BRIDGE_PATH_LV2_X11 = 4
  561. OPTION_BRIDGE_PATH_VST_QT4 = 5
  562. OPTION_BRIDGE_PATH_WINVST = 6
  563. # enum CallbackType
  564. CALLBACK_DEBUG = 0
  565. CALLBACK_PARAMETER_CHANGED = 1 # parameter_id, 0, value
  566. CALLBACK_PROGRAM_CHANGED = 2 # program_id, 0, 0
  567. CALLBACK_MIDI_PROGRAM_CHANGED = 3 # midi_program_id, 0, 0
  568. CALLBACK_NOTE_ON = 4 # key, velocity, 0
  569. CALLBACK_NOTE_OFF = 5 # key, velocity, 0
  570. CALLBACK_SHOW_GUI = 6 # show? (0|1, -1=quit), 0, 0
  571. CALLBACK_RESIZE_GUI = 7 # width, height, 0
  572. CALLBACK_UPDATE = 8
  573. CALLBACK_RELOAD_INFO = 9
  574. CALLBACK_RELOAD_PARAMETERS = 10
  575. CALLBACK_RELOAD_PROGRAMS = 11
  576. CALLBACK_RELOAD_ALL = 12
  577. CALLBACK_QUIT = 13
  578. class ParameterData(Structure):
  579. _fields_ = [
  580. ("type", c_enum),
  581. ("index", c_int32),
  582. ("rindex", c_int32),
  583. ("hints", c_int32),
  584. ("midi_channel", c_uint8),
  585. ("midi_cc", c_int16)
  586. ]
  587. class ParameterRanges(Structure):
  588. _fields_ = [
  589. ("def", c_double),
  590. ("min", c_double),
  591. ("max", c_double),
  592. ("step", c_double),
  593. ("step_small", c_double),
  594. ("step_large", c_double)
  595. ]
  596. class CustomData(Structure):
  597. _fields_ = [
  598. ("type", c_enum),
  599. ("key", c_char_p),
  600. ("value", c_char_p)
  601. ]
  602. class GuiData(Structure):
  603. _fields_ = [
  604. ("type", c_enum),
  605. ("visible", c_bool),
  606. ("resizable", c_bool),
  607. ("width", c_uint),
  608. ("height", c_uint),
  609. ("name", c_char_p),
  610. ("show_now", c_bool)
  611. ]
  612. class PluginInfo(Structure):
  613. _fields_ = [
  614. ("valid", c_bool),
  615. ("type", c_enum),
  616. ("category", c_enum),
  617. ("hints", c_uint),
  618. ("binary", c_char_p),
  619. ("name", c_char_p),
  620. ("label", c_char_p),
  621. ("maker", c_char_p),
  622. ("copyright", c_char_p),
  623. ("unique_id", c_long)
  624. ]
  625. class PortCountInfo(Structure):
  626. _fields_ = [
  627. ("valid", c_bool),
  628. ("ins", c_uint32),
  629. ("outs", c_uint32),
  630. ("total", c_uint32)
  631. ]
  632. class ParameterInfo(Structure):
  633. _fields_ = [
  634. ("valid", c_bool),
  635. ("name", c_char_p),
  636. ("symbol", c_char_p),
  637. ("label", c_char_p),
  638. ("scalepoint_count", c_uint32)
  639. ]
  640. class ScalePointInfo(Structure):
  641. _fields_ = [
  642. ("valid", c_bool),
  643. ("value", c_double),
  644. ("label", c_char_p)
  645. ]
  646. class MidiProgramInfo(Structure):
  647. _fields_ = [
  648. ("valid", c_bool),
  649. ("bank", c_uint32),
  650. ("program", c_uint32),
  651. ("label", c_char_p)
  652. ]
  653. class WinVstBaseInfo(Structure):
  654. _fields_ = [
  655. ("category", c_enum),
  656. ("hints", c_uint),
  657. ("name", c_char_p),
  658. ("maker", c_char_p),
  659. ("unique_id", c_long),
  660. ("ains", c_uint32),
  661. ("aouts", c_uint32)
  662. ]
  663. # ------------------------------------------------------------------------------------------------
  664. # Backend C++ -> Python object
  665. class Host(object):
  666. def __init__(self, cwd):
  667. super(Host, self).__init__()
  668. if (WINDOWS):
  669. libname = "carla_backend.dll"
  670. elif (MACOS):
  671. libname = "carla_backend.dylib"
  672. else:
  673. libname = "carla_backend.so"
  674. self.lib = None #cdll.LoadLibrary(os.path.join(cwd, "carla", libname))
  675. def carla_init(self, client_name):
  676. return True
  677. #self.lib.carla_init.argtypes = [c_char_p]
  678. #self.lib.carla_init.restype = c_bool
  679. #return self.lib.carla_init(client_name)
  680. def carla_close(self):
  681. return True
  682. #self.lib.carla_close.argtypes = None
  683. #self.lib.carla_close.restype = c_bool
  684. #return self.lib.carla_close()
  685. def carla_is_engine_running(self):
  686. return False
  687. #self.lib.carla_is_engine_running.argtypes = None
  688. #self.lib.carla_is_engine_running.restype = c_bool
  689. #return self.lib.carla_is_engine_running()
  690. def add_plugin(self, ptype, filename, label, extra_stuff):
  691. self.lib.add_plugin.argtypes = [c_enum, c_char_p, c_char_p, c_void_p]
  692. self.lib.add_plugin.restype = c_short
  693. return self.lib.add_plugin(ptype, filename, label, cast(extra_stuff, c_void_p))
  694. def remove_plugin(self, plugin_id):
  695. self.lib.remove_plugin.argtypes = [c_ushort]
  696. self.lib.remove_plugin.restype = c_bool
  697. return self.lib.remove_plugin(plugin_id)
  698. def get_plugin_info(self, plugin_id):
  699. self.lib.get_plugin_info.argtypes = [c_ushort]
  700. self.lib.get_plugin_info.restype = POINTER(PluginInfo)
  701. return struct_to_dict(self.lib.get_plugin_info(plugin_id).contents)
  702. def get_audio_port_count_info(self, plugin_id):
  703. self.lib.get_audio_port_count_info.argtypes = [c_ushort]
  704. self.lib.get_audio_port_count_info.restype = POINTER(PortCountInfo)
  705. return struct_to_dict(self.lib.get_audio_port_count_info(plugin_id).contents)
  706. def get_midi_port_count_info(self, plugin_id):
  707. self.lib.get_midi_port_count_info.argtypes = [c_ushort]
  708. self.lib.get_midi_port_count_info.restype = POINTER(PortCountInfo)
  709. return struct_to_dict(self.lib.get_midi_port_count_info(plugin_id).contents)
  710. def get_parameter_count_info(self, plugin_id):
  711. self.lib.get_parameter_count_info.argtypes = [c_ushort]
  712. self.lib.get_parameter_count_info.restype = POINTER(PortCountInfo)
  713. return struct_to_dict(self.lib.get_parameter_count_info(plugin_id).contents)
  714. def get_parameter_info(self, plugin_id, parameter_id):
  715. self.lib.get_parameter_info.argtypes = [c_ushort, c_uint32]
  716. self.lib.get_parameter_info.restype = POINTER(ParameterInfo)
  717. return struct_to_dict(self.lib.get_parameter_info(plugin_id, parameter_id).contents)
  718. def get_scalepoint_info(self, plugin_id, parameter_id, scalepoint_id):
  719. self.lib.get_scalepoint_info.argtypes = [c_ushort, c_uint32, c_uint32]
  720. self.lib.get_scalepoint_info.restype = POINTER(ScalePointInfo)
  721. return struct_to_dict(self.lib.get_scalepoint_info(plugin_id, parameter_id, scalepoint_id).contents)
  722. def get_midi_program_info(self, plugin_id, midi_program_id):
  723. self.lib.get_midi_program_info.argtypes = [c_ushort, c_uint32]
  724. self.lib.get_midi_program_info.restype = POINTER(MidiProgramInfo)
  725. return struct_to_dict(self.lib.get_midi_program_info(plugin_id, midi_program_id).contents)
  726. def get_parameter_data(self, plugin_id, parameter_id):
  727. self.lib.get_parameter_data.argtypes = [c_ushort, c_uint32]
  728. self.lib.get_parameter_data.restype = POINTER(ParameterData)
  729. return struct_to_dict(self.lib.get_parameter_data(plugin_id, parameter_id).contents)
  730. def get_parameter_ranges(self, plugin_id, parameter_id):
  731. self.lib.get_parameter_ranges.argtypes = [c_ushort, c_uint32]
  732. self.lib.get_parameter_ranges.restype = POINTER(ParameterRanges)
  733. return struct_to_dict(self.lib.get_parameter_ranges(plugin_id, parameter_id).contents)
  734. def get_custom_data(self, plugin_id, custom_data_id):
  735. self.lib.get_custom_data.argtypes = [c_ushort, c_uint32]
  736. self.lib.get_custom_data.restype = POINTER(CustomData)
  737. return struct_to_dict(self.lib.get_custom_data(plugin_id, custom_data_id).contents)
  738. def get_chunk_data(self, plugin_id):
  739. self.lib.get_chunk_data.argtypes = [c_ushort]
  740. self.lib.get_chunk_data.restype = c_char_p
  741. return self.lib.get_chunk_data(plugin_id)
  742. def get_gui_data(self, plugin_id):
  743. self.lib.get_gui_data.argtypes = [c_ushort]
  744. self.lib.get_gui_data.restype = POINTER(GuiData)
  745. return struct_to_dict(self.lib.get_gui_data(plugin_id).contents)
  746. def get_parameter_count(self, plugin_id):
  747. self.lib.get_parameter_count.argtypes = [c_ushort]
  748. self.lib.get_parameter_count.restype = c_uint32
  749. return self.lib.get_parameter_count(plugin_id)
  750. def get_program_count(self, plugin_id):
  751. self.lib.get_program_count.argtypes = [c_ushort]
  752. self.lib.get_program_count.restype = c_uint32
  753. return self.lib.get_program_count(plugin_id)
  754. def get_midi_program_count(self, plugin_id):
  755. self.lib.get_midi_program_count.argtypes = [c_ushort]
  756. self.lib.get_midi_program_count.restype = c_uint32
  757. return self.lib.get_midi_program_count(plugin_id)
  758. def get_custom_data_count(self, plugin_id):
  759. self.lib.get_custom_data_count.argtypes = [c_ushort]
  760. self.lib.get_custom_data_count.restype = c_uint32
  761. return self.lib.get_custom_data_count(plugin_id)
  762. def get_program_name(self, plugin_id, program_id):
  763. self.lib.get_program_name.argtypes = [c_ushort, c_uint32]
  764. self.lib.get_program_name.restype = c_char_p
  765. return self.lib.get_program_name(plugin_id, program_id)
  766. def get_midi_program_name(self, plugin_id, midi_program_id):
  767. self.lib.get_midi_program_name.argtypes = [c_ushort, c_uint32]
  768. self.lib.get_midi_program_name.restype = c_char_p
  769. return self.lib.get_midi_program_name(plugin_id, midi_program_id)
  770. def get_real_plugin_name(self, plugin_id):
  771. self.lib.get_real_plugin_name.argtypes = [c_ushort]
  772. self.lib.get_real_plugin_name.restype = c_char_p
  773. return self.lib.get_real_plugin_name(plugin_id)
  774. def get_current_program_index(self, plugin_id):
  775. self.lib.get_current_program_index.argtypes = [c_ushort]
  776. self.lib.get_current_program_index.restype = c_int32
  777. return self.lib.get_current_program_index(plugin_id)
  778. def get_current_midi_program_index(self, plugin_id):
  779. self.lib.get_current_midi_program_index.argtypes = [c_ushort]
  780. self.lib.get_current_midi_program_index.restype = c_int32
  781. return self.lib.get_current_midi_program_index(plugin_id)
  782. def get_default_parameter_value(self, plugin_id, parameter_id):
  783. self.lib.get_default_parameter_value.argtypes = [c_ushort, c_uint32]
  784. self.lib.get_default_parameter_value.restype = c_double
  785. return self.lib.get_default_parameter_value(plugin_id, parameter_id)
  786. def get_current_parameter_value(self, plugin_id, parameter_id):
  787. self.lib.get_current_parameter_value.argtypes = [c_ushort, c_uint32]
  788. self.lib.get_current_parameter_value.restype = c_double
  789. return self.lib.get_current_parameter_value(plugin_id, parameter_id)
  790. def get_input_peak_value(self, plugin_id, port_id):
  791. self.lib.get_input_peak_value.argtypes = [c_ushort, c_ushort]
  792. self.lib.get_input_peak_value.restype = c_double
  793. return self.lib.get_input_peak_value(plugin_id, port_id)
  794. def get_output_peak_value(self, plugin_id, port_id):
  795. self.lib.get_output_peak_value.argtypes = [c_ushort, c_ushort]
  796. self.lib.get_output_peak_value.restype = c_double
  797. return self.lib.get_output_peak_value(plugin_id, port_id)
  798. def set_active(self, plugin_id, onoff):
  799. self.lib.set_active.argtypes = [c_ushort, c_bool]
  800. self.lib.set_active.restype = None
  801. self.lib.set_active(plugin_id, onoff)
  802. def set_drywet(self, plugin_id, value):
  803. self.lib.set_drywet.argtypes = [c_ushort, c_double]
  804. self.lib.set_drywet.restype = None
  805. self.lib.set_drywet(plugin_id, value)
  806. def set_vol(self, plugin_id, value):
  807. self.lib.set_vol.argtypes = [c_ushort, c_double]
  808. self.lib.set_vol.restype = None
  809. self.lib.set_vol(plugin_id, value)
  810. def set_balance_left(self, plugin_id, value):
  811. self.lib.set_balance_left.argtypes = [c_ushort, c_double]
  812. self.lib.set_balance_left.restype = None
  813. self.lib.set_balance_left(plugin_id, value)
  814. def set_balance_right(self, plugin_id, value):
  815. self.lib.set_balance_right.argtypes = [c_ushort, c_double]
  816. self.lib.set_balance_right.restype = None
  817. self.lib.set_balance_right(plugin_id, value)
  818. def set_parameter_value(self, plugin_id, parameter_id, value):
  819. self.lib.set_parameter_value.argtypes = [c_ushort, c_uint32, c_double]
  820. self.lib.set_parameter_value.restype = None
  821. self.lib.set_parameter_value(plugin_id, parameter_id, value)
  822. def set_parameter_midi_channel(self, plugin_id, parameter_id, channel):
  823. self.lib.set_parameter_midi_channel.argtypes = [c_ushort, c_uint32, c_uint8]
  824. self.lib.set_parameter_midi_channel.restype = None
  825. self.lib.set_parameter_midi_channel(plugin_id, parameter_id, channel)
  826. def set_parameter_midi_cc(self, plugin_id, parameter_id, cc):
  827. self.lib.set_parameter_midi_cc.argtypes = [c_ushort, c_uint32, c_int16]
  828. self.lib.set_parameter_midi_cc.restype = None
  829. self.lib.set_parameter_midi_cc(plugin_id, parameter_id, cc)
  830. def set_program(self, plugin_id, program_id):
  831. self.lib.set_program.argtypes = [c_ushort, c_uint32]
  832. self.lib.set_program.restype = None
  833. self.lib.set_program(plugin_id, program_id)
  834. def set_midi_program(self, plugin_id, midi_program_id):
  835. self.lib.set_midi_program.argtypes = [c_ushort, c_uint32]
  836. self.lib.set_midi_program.restype = None
  837. self.lib.set_midi_program(plugin_id, midi_program_id)
  838. def set_custom_data(self, plugin_id, dtype, key, value):
  839. self.lib.set_custom_data.argtypes = [c_ushort, c_enum, c_char_p, c_char_p]
  840. self.lib.set_custom_data.restype = None
  841. return self.lib.set_custom_data(plugin_id, dtype, key, value)
  842. def set_chunk_data(self, plugin_id, chunk_data):
  843. self.lib.set_chunk_data.argtypes = [c_ushort, c_char_p]
  844. self.lib.set_chunk_data.restype = None
  845. self.lib.set_chunk_data(plugin_id, chunk_data)
  846. def set_gui_data(self, plugin_id, data, gui_addr):
  847. self.lib.set_gui_data.argtypes = [c_ushort, c_int, c_intptr]
  848. self.lib.set_gui_data.restype = None
  849. self.lib.set_gui_data(plugin_id, data, gui_addr)
  850. def show_gui(self, plugin_id, yesno):
  851. self.lib.show_gui.argtypes = [c_ushort, c_bool]
  852. self.lib.show_gui.restype = None
  853. self.lib.show_gui(plugin_id, yesno)
  854. def idle_gui(self, plugin_id):
  855. self.lib.idle_gui.argtypes = [c_ushort]
  856. self.lib.idle_gui.restype = None
  857. self.lib.idle_gui(plugin_id)
  858. def send_midi_note(self, plugin_id, onoff, note, velocity):
  859. self.lib.send_midi_note.argtypes = [c_ushort, c_bool, c_uint8, c_uint8]
  860. self.lib.send_midi_note.restype = None
  861. self.lib.send_midi_note(plugin_id, onoff, note, velocity)
  862. def prepare_for_save(self, plugin_id):
  863. self.lib.prepare_for_save.argtypes = [c_ushort]
  864. self.lib.prepare_for_save.restype = None
  865. self.lib.prepare_for_save(plugin_id)
  866. def set_callback_function(self, func):
  867. global Callback
  868. #Callback = CFUNCTYPE(None, c_enum, c_ushort, c_int, c_int, c_double)(func)
  869. #self.lib.set_callback_function.argtypes = [] # TODO
  870. #self.lib.set_callback_function.restype = None
  871. #self.lib.set_callback_function(Callback)
  872. def set_option(self, option, value, value_str):
  873. self.lib.set_option.argtypes = [c_enum, c_int, c_char_p]
  874. self.lib.set_option.restype = None
  875. self.lib.set_option(option, value, value_str)
  876. def get_last_error(self):
  877. return ""
  878. #self.lib.get_last_error.argtypes = None
  879. #self.lib.get_last_error.restype = c_char_p
  880. #return self.lib.get_last_error()
  881. def get_host_osc_url(self):
  882. return ""
  883. #self.lib.get_host_osc_url.argtypes = None
  884. #self.lib.get_host_osc_url.restype = c_char_p
  885. #return self.lib.get_host_osc_url()
  886. def get_host_client_name(self):
  887. return ""
  888. #self.lib.get_host_client_name.argtypes = None
  889. #self.lib.get_host_client_name.restype = c_char_p
  890. #return self.lib.get_host_client_name()
  891. def get_buffer_size(self):
  892. self.lib.get_buffer_size.argtypes = None
  893. self.lib.get_buffer_size.restype = c_uint32
  894. return self.lib.get_buffer_size()
  895. def get_sample_rate(self):
  896. self.lib.get_sample_rate.argtypes = None
  897. self.lib.get_sample_rate.restype = c_double
  898. return self.lib.get_sample_rate()
  899. def get_latency(self):
  900. self.lib.get_latency.argtypes = None
  901. self.lib.get_latency.restype = c_double
  902. return self.lib.get_latency()
  903. # ------------------------------------------------------------------------------------------------
  904. # Default Plugin Folders (set)
  905. LADSPA_PATH_env = os.getenv("LADSPA_PATH")
  906. DSSI_PATH_env = os.getenv("DSSI_PATH")
  907. LV2_PATH_env = os.getenv("LV2_PATH")
  908. VST_PATH_env = os.getenv("VST_PATH")
  909. SF2_PATH_env = os.getenv("SF2_PATH")
  910. if (LADSPA_PATH_env):
  911. LADSPA_PATH = LADSPA_PATH_env.split(splitter)
  912. else:
  913. LADSPA_PATH = DEFAULT_LADSPA_PATH
  914. if (DSSI_PATH_env):
  915. DSSI_PATH = DSSI_PATH_env.split(splitter)
  916. else:
  917. DSSI_PATH = DEFAULT_DSSI_PATH
  918. if (LV2_PATH_env):
  919. LV2_PATH = LV2_PATH_env.split(splitter)
  920. else:
  921. LV2_PATH = DEFAULT_LV2_PATH
  922. if (VST_PATH_env):
  923. VST_PATH = VST_PATH_env.split(splitter)
  924. else:
  925. VST_PATH = DEFAULT_VST_PATH
  926. if (SF2_PATH_env):
  927. SF2_PATH = SF2_PATH_env.split(splitter)
  928. else:
  929. SF2_PATH = DEFAULT_SF2_PATH
  930. if (haveRDF):
  931. LADSPA_RDF_PATH_env = os.getenv("LADSPA_RDF_PATH")
  932. if (LADSPA_RDF_PATH_env):
  933. ladspa_rdf.set_rdf_path(LADSPA_RDF_PATH_env.split(splitter))
  934. #lv2_rdf.set_rdf_path(LV2_PATH)