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.

799 lines
27KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # LADSPA RDF python support
  4. # Copyright (C) 2011-2013 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. # C types
  19. # Imports (Global)
  20. from ctypes import *
  21. from copy import deepcopy
  22. # Null type
  23. c_nullptr = None
  24. # Base Types
  25. LADSPA_Data = c_float
  26. LADSPA_Property = c_int
  27. LADSPA_PluginType = c_ulonglong
  28. # Unit Types
  29. LADSPA_UNIT_DB = 0x01
  30. LADSPA_UNIT_COEF = 0x02
  31. LADSPA_UNIT_HZ = 0x04
  32. LADSPA_UNIT_S = 0x08
  33. LADSPA_UNIT_MS = 0x10
  34. LADSPA_UNIT_MIN = 0x20
  35. LADSPA_UNIT_CLASS_AMPLITUDE = LADSPA_UNIT_DB|LADSPA_UNIT_COEF
  36. LADSPA_UNIT_CLASS_FREQUENCY = LADSPA_UNIT_HZ
  37. LADSPA_UNIT_CLASS_TIME = LADSPA_UNIT_S|LADSPA_UNIT_MS|LADSPA_UNIT_MIN
  38. # Port Types (Official API)
  39. LADSPA_PORT_INPUT = 0x1
  40. LADSPA_PORT_OUTPUT = 0x2
  41. LADSPA_PORT_CONTROL = 0x4
  42. LADSPA_PORT_AUDIO = 0x8
  43. # Port Hints
  44. LADSPA_PORT_UNIT = 0x1
  45. LADSPA_PORT_DEFAULT = 0x2
  46. LADSPA_PORT_LABEL = 0x4
  47. # Plugin Types
  48. LADSPA_PLUGIN_UTILITY = 0x000000001
  49. LADSPA_PLUGIN_GENERATOR = 0x000000002
  50. LADSPA_PLUGIN_SIMULATOR = 0x000000004
  51. LADSPA_PLUGIN_OSCILLATOR = 0x000000008
  52. LADSPA_PLUGIN_TIME = 0x000000010
  53. LADSPA_PLUGIN_DELAY = 0x000000020
  54. LADSPA_PLUGIN_PHASER = 0x000000040
  55. LADSPA_PLUGIN_FLANGER = 0x000000080
  56. LADSPA_PLUGIN_CHORUS = 0x000000100
  57. LADSPA_PLUGIN_REVERB = 0x000000200
  58. LADSPA_PLUGIN_FREQUENCY = 0x000000400
  59. LADSPA_PLUGIN_FREQUENCY_METER = 0x000000800
  60. LADSPA_PLUGIN_FILTER = 0x000001000
  61. LADSPA_PLUGIN_LOWPASS = 0x000002000
  62. LADSPA_PLUGIN_HIGHPASS = 0x000004000
  63. LADSPA_PLUGIN_BANDPASS = 0x000008000
  64. LADSPA_PLUGIN_COMB = 0x000010000
  65. LADSPA_PLUGIN_ALLPASS = 0x000020000
  66. LADSPA_PLUGIN_EQ = 0x000040000
  67. LADSPA_PLUGIN_PARAEQ = 0x000080000
  68. LADSPA_PLUGIN_MULTIEQ = 0x000100000
  69. LADSPA_PLUGIN_AMPLITUDE = 0x000200000
  70. LADSPA_PLUGIN_PITCH = 0x000400000
  71. LADSPA_PLUGIN_AMPLIFIER = 0x000800000
  72. LADSPA_PLUGIN_WAVESHAPER = 0x001000000
  73. LADSPA_PLUGIN_MODULATOR = 0x002000000
  74. LADSPA_PLUGIN_DISTORTION = 0x004000000
  75. LADSPA_PLUGIN_DYNAMICS = 0x008000000
  76. LADSPA_PLUGIN_COMPRESSOR = 0x010000000
  77. LADSPA_PLUGIN_EXPANDER = 0x020000000
  78. LADSPA_PLUGIN_LIMITER = 0x040000000
  79. LADSPA_PLUGIN_GATE = 0x080000000
  80. LADSPA_PLUGIN_SPECTRAL = 0x100000000
  81. LADSPA_PLUGIN_NOTCH = 0x200000000
  82. LADSPA_GROUP_DYNAMICS = LADSPA_PLUGIN_DYNAMICS | LADSPA_PLUGIN_COMPRESSOR | LADSPA_PLUGIN_EXPANDER | LADSPA_PLUGIN_LIMITER | LADSPA_PLUGIN_GATE
  83. LADSPA_GROUP_AMPLITUDE = LADSPA_PLUGIN_AMPLITUDE | LADSPA_PLUGIN_AMPLIFIER | LADSPA_PLUGIN_WAVESHAPER | LADSPA_PLUGIN_MODULATOR | LADSPA_PLUGIN_DISTORTION | LADSPA_GROUP_DYNAMICS
  84. LADSPA_GROUP_EQ = LADSPA_PLUGIN_EQ | LADSPA_PLUGIN_PARAEQ | LADSPA_PLUGIN_MULTIEQ
  85. LADSPA_GROUP_FILTER = LADSPA_PLUGIN_FILTER | LADSPA_PLUGIN_LOWPASS | LADSPA_PLUGIN_HIGHPASS | LADSPA_PLUGIN_BANDPASS | LADSPA_PLUGIN_COMB | LADSPA_PLUGIN_ALLPASS | LADSPA_PLUGIN_NOTCH
  86. LADSPA_GROUP_FREQUENCY = LADSPA_PLUGIN_FREQUENCY | LADSPA_PLUGIN_FREQUENCY_METER | LADSPA_GROUP_FILTER | LADSPA_GROUP_EQ | LADSPA_PLUGIN_PITCH
  87. LADSPA_GROUP_SIMULATOR = LADSPA_PLUGIN_SIMULATOR | LADSPA_PLUGIN_REVERB
  88. LADSPA_GROUP_TIME = LADSPA_PLUGIN_TIME | LADSPA_PLUGIN_DELAY | LADSPA_PLUGIN_PHASER | LADSPA_PLUGIN_FLANGER | LADSPA_PLUGIN_CHORUS | LADSPA_PLUGIN_REVERB
  89. LADSPA_GROUP_GENERATOR = LADSPA_PLUGIN_GENERATOR | LADSPA_PLUGIN_OSCILLATOR
  90. # Scale Point
  91. class LADSPA_RDF_ScalePoint(Structure):
  92. _fields_ = [
  93. ("Value", LADSPA_Data),
  94. ("Label", c_char_p)
  95. ]
  96. # Port
  97. class LADSPA_RDF_Port(Structure):
  98. _fields_ = [
  99. ("Type", LADSPA_Property),
  100. ("Hints", LADSPA_Property),
  101. ("Label", c_char_p),
  102. ("Default", LADSPA_Data),
  103. ("Unit", LADSPA_Property),
  104. ("ScalePointCount", c_ulong),
  105. ("ScalePoints", POINTER(LADSPA_RDF_ScalePoint))
  106. ]
  107. # Plugin
  108. class LADSPA_RDF_Descriptor(Structure):
  109. _fields_ = [
  110. ("Type", LADSPA_PluginType),
  111. ("UniqueID", c_ulong),
  112. ("Title", c_char_p),
  113. ("Creator", c_char_p),
  114. ("PortCount", c_ulong),
  115. ("Ports", POINTER(LADSPA_RDF_Port))
  116. ]
  117. # ------------------------------------------------------------------------------------------------------------
  118. # Python compatible C types
  119. PyLADSPA_RDF_ScalePoint = {
  120. 'Value': 0.0,
  121. 'Label': ""
  122. }
  123. PyLADSPA_RDF_Port = {
  124. 'Type': 0x0,
  125. 'Hints': 0x0,
  126. 'Label': "",
  127. 'Default': 0.0,
  128. 'Unit': 0x0,
  129. 'ScalePointCount': 0,
  130. 'ScalePoints': [],
  131. # Only here to help, NOT in the API:
  132. 'index': 0
  133. }
  134. PyLADSPA_RDF_Descriptor = {
  135. 'Type': 0x0,
  136. 'UniqueID': 0,
  137. 'Title': "",
  138. 'Creator': "",
  139. 'PortCount': 0,
  140. 'Ports': []
  141. }
  142. # ------------------------------------------------------------------------------------------------------------
  143. # RDF data and conversions
  144. # Namespaces
  145. NS_dc = "http://purl.org/dc/elements/1.1/"
  146. NS_rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  147. NS_rdfs = "http://www.w3.org/2000/01/rdf-schema#"
  148. NS_ladspa = "http://ladspa.org/ontology#"
  149. NS_caps = "http://quitte.de/dsp/caps.html#"
  150. # Prefixes (sorted alphabetically and by type)
  151. rdf_prefix = {
  152. # Base types
  153. 'dc:creator': NS_dc + "creator",
  154. 'dc:rights': NS_dc + "rights",
  155. 'dc:title': NS_dc + "title",
  156. 'rdf:value': NS_rdf + "value",
  157. 'rdf:type': NS_rdf + "type",
  158. # LADSPA Stuff
  159. 'ladspa:forPort': NS_ladspa + "forPort",
  160. 'ladspa:hasLabel': NS_ladspa + "hasLabel",
  161. 'ladspa:hasPoint': NS_ladspa + "hasPoint",
  162. 'ladspa:hasPort': NS_ladspa + "hasPort",
  163. 'ladspa:hasPortValue': NS_ladspa + "hasPortValue",
  164. 'ladspa:hasScale': NS_ladspa + "hasScale",
  165. 'ladspa:hasSetting': NS_ladspa + "hasSetting",
  166. 'ladspa:hasUnit': NS_ladspa + "hasUnit",
  167. # LADSPA Extensions
  168. 'ladspa:NotchPlugin': NS_ladspa + "NotchPlugin",
  169. 'ladspa:SpectralPlugin': NS_ladspa + "SpectralPlugin"
  170. }
  171. def get_c_plugin_type(value):
  172. valueStr = value.replace(NS_ladspa, "")
  173. ret = 0x0
  174. if valueStr == "Plugin":
  175. pass
  176. elif valueStr == "UtilityPlugin":
  177. ret = LADSPA_PLUGIN_UTILITY
  178. elif valueStr == "GeneratorPlugin":
  179. ret = LADSPA_PLUGIN_GENERATOR
  180. elif valueStr == "SimulatorPlugin":
  181. ret = LADSPA_PLUGIN_SIMULATOR
  182. elif valueStr == "OscillatorPlugin":
  183. ret = LADSPA_PLUGIN_OSCILLATOR
  184. elif valueStr == "TimePlugin":
  185. ret = LADSPA_PLUGIN_TIME
  186. elif valueStr == "DelayPlugin":
  187. ret = LADSPA_PLUGIN_DELAY
  188. elif valueStr == "PhaserPlugin":
  189. ret = LADSPA_PLUGIN_PHASER
  190. elif valueStr == "FlangerPlugin":
  191. ret = LADSPA_PLUGIN_FLANGER
  192. elif valueStr == "ChorusPlugin":
  193. ret = LADSPA_PLUGIN_CHORUS
  194. elif valueStr == "ReverbPlugin":
  195. ret = LADSPA_PLUGIN_REVERB
  196. elif valueStr == "FrequencyPlugin":
  197. ret = LADSPA_PLUGIN_FREQUENCY
  198. elif valueStr == "FrequencyMeterPlugin":
  199. ret = LADSPA_PLUGIN_FREQUENCY_METER
  200. elif valueStr == "FilterPlugin":
  201. ret = LADSPA_PLUGIN_FILTER
  202. elif valueStr == "LowpassPlugin":
  203. ret = LADSPA_PLUGIN_LOWPASS
  204. elif valueStr == "HighpassPlugin":
  205. ret = LADSPA_PLUGIN_HIGHPASS
  206. elif valueStr == "BandpassPlugin":
  207. ret = LADSPA_PLUGIN_BANDPASS
  208. elif valueStr == "CombPlugin":
  209. ret = LADSPA_PLUGIN_COMB
  210. elif valueStr == "AllpassPlugin":
  211. ret = LADSPA_PLUGIN_ALLPASS
  212. elif valueStr == "EQPlugin":
  213. ret = LADSPA_PLUGIN_EQ
  214. elif valueStr == "ParaEQPlugin":
  215. ret = LADSPA_PLUGIN_PARAEQ
  216. elif valueStr == "MultiEQPlugin":
  217. ret = LADSPA_PLUGIN_MULTIEQ
  218. elif valueStr == "AmplitudePlugin":
  219. ret = LADSPA_PLUGIN_AMPLITUDE
  220. elif valueStr == "PitchPlugin":
  221. ret = LADSPA_PLUGIN_PITCH
  222. elif valueStr == "AmplifierPlugin":
  223. ret = LADSPA_PLUGIN_AMPLIFIER
  224. elif valueStr == "WaveshaperPlugin":
  225. ret = LADSPA_PLUGIN_WAVESHAPER
  226. elif valueStr == "ModulatorPlugin":
  227. ret = LADSPA_PLUGIN_MODULATOR
  228. elif valueStr == "DistortionPlugin":
  229. ret = LADSPA_PLUGIN_DISTORTION
  230. elif valueStr == "DynamicsPlugin":
  231. ret = LADSPA_PLUGIN_DYNAMICS
  232. elif valueStr == "CompressorPlugin":
  233. ret = LADSPA_PLUGIN_COMPRESSOR
  234. elif valueStr == "ExpanderPlugin":
  235. ret = LADSPA_PLUGIN_EXPANDER
  236. elif valueStr == "LimiterPlugin":
  237. ret = LADSPA_PLUGIN_LIMITER
  238. elif valueStr == "GatePlugin":
  239. ret = LADSPA_PLUGIN_GATE
  240. elif valueStr == "SpectralPlugin":
  241. ret = LADSPA_PLUGIN_SPECTRAL
  242. elif valueStr == "NotchPlugin":
  243. ret = LADSPA_PLUGIN_NOTCH
  244. elif valueStr == "MixerPlugin":
  245. ret = LADSPA_PLUGIN_EQ
  246. else:
  247. print("LADSPA_RDF - Got an unknown plugin type '%s'" % valueStr)
  248. return ret
  249. def get_c_port_type(value):
  250. valueStr = value.replace(NS_ladspa, "")
  251. ret = 0x0
  252. if valueStr == "Port":
  253. pass
  254. elif valueStr == "ControlPort":
  255. ret = LADSPA_PORT_CONTROL
  256. elif valueStr == "AudioPort":
  257. ret = LADSPA_PORT_AUDIO
  258. elif valueStr == "InputPort":
  259. ret = LADSPA_PORT_INPUT
  260. elif valueStr == "OutputPort":
  261. ret = LADSPA_PORT_OUTPUT
  262. elif valueStr in ("ControlInputPort", "InputControlPort"):
  263. ret = LADSPA_PORT_CONTROL|LADSPA_PORT_INPUT
  264. elif valueStr in ("ControlOutputPort", "OutputControlPort"):
  265. ret = LADSPA_PORT_CONTROL|LADSPA_PORT_OUTPUT
  266. elif valueStr in ("AudioInputPort", "InputAudioPort"):
  267. ret = LADSPA_PORT_AUDIO|LADSPA_PORT_INPUT
  268. elif valueStr in ("AudioOutputPort", "OutputAudioPort"):
  269. ret = LADSPA_PORT_AUDIO|LADSPA_PORT_OUTPUT
  270. else:
  271. print("LADSPA_RDF - Got an unknown port type '%s'" % valueStr)
  272. return ret
  273. def get_c_unit_type(value):
  274. valueStr = value.replace(NS_ladspa, "")
  275. ret = 0x0
  276. if valueStr in ("Unit", "Units", "AmplitudeUnits", "FrequencyUnits", "TimeUnits"):
  277. pass
  278. elif valueStr == "dB":
  279. ret = LADSPA_UNIT_DB
  280. elif valueStr == "coef":
  281. ret = LADSPA_UNIT_COEF
  282. elif valueStr == "Hz":
  283. ret = LADSPA_UNIT_HZ
  284. elif valueStr == "seconds":
  285. ret = LADSPA_UNIT_S
  286. elif valueStr == "milliseconds":
  287. ret = LADSPA_UNIT_MS
  288. elif valueStr == "minutes":
  289. ret = LADSPA_UNIT_MIN
  290. else:
  291. print("LADSPA_RDF - Got an unknown unit type '%s'" % valueStr)
  292. return ret
  293. # ------------------------------------------------------------------------------------------------------------
  294. # Global objects
  295. LADSPA_RDF_PATH = ("/usr/share/ladspa/rdf", "/usr/local/share/ladspa/rdf")
  296. LADSPA_Plugins = []
  297. # Set LADSPA_RDF_PATH variable
  298. def set_rdf_path(PATH):
  299. global LADSPA_RDF_PATH
  300. LADSPA_RDF_PATH = PATH
  301. # ------------------------------------------------------------------------------------------------------------
  302. # Helper methods
  303. LADSPA_RDF_TYPE_PLUGIN = 1
  304. LADSPA_RDF_TYPE_PORT = 2
  305. # Check RDF Type
  306. def rdf_is_type(subject, compare):
  307. if isinstance(subject, URIRef) and NS_ladspa in subject:
  308. if compare == LADSPA_RDF_TYPE_PLUGIN:
  309. return bool(to_plugin_number(subject).isdigit())
  310. elif compare == LADSPA_RDF_TYPE_PORT:
  311. return bool("." in to_plugin_number(subject))
  312. else:
  313. return False
  314. def to_float(rdfItem):
  315. return float(str(rdfItem).replace("f", ""))
  316. # Convert RDF LADSPA subject into a number
  317. def to_plugin_number(subject):
  318. return str(subject).replace(NS_ladspa, "")
  319. # Convert RDF LADSPA subject into a plugin and port number
  320. def to_plugin_and_port_number(subject):
  321. numbers = str(subject).replace(NS_ladspa, "").split(".")
  322. return (numbers[0], numbers[1])
  323. # Convert RDF LADSPA subject into a port number
  324. def to_plugin_port(subject):
  325. return to_plugin_and_port_number(subject)[1]
  326. # ------------------------------------------------------------------------------------------------------------
  327. # RDF store/retrieve data methods
  328. def check_and_add_plugin(pluginId):
  329. global LADSPA_Plugins
  330. for i in range(len(LADSPA_Plugins)):
  331. if LADSPA_Plugins[i]['UniqueID'] == pluginId:
  332. return i
  333. else:
  334. plugin = deepcopy(PyLADSPA_RDF_Descriptor)
  335. plugin['UniqueID'] = pluginId
  336. LADSPA_Plugins.append(plugin)
  337. return len(LADSPA_Plugins) - 1
  338. def set_plugin_value(pluginId, key, value):
  339. global LADSPA_Plugins
  340. index = check_and_add_plugin(pluginId)
  341. LADSPA_Plugins[index][key] = value
  342. def add_plugin_value(pluginId, key, value):
  343. global LADSPA_Plugins
  344. index = check_and_add_plugin(pluginId)
  345. LADSPA_Plugins[index][key] += value
  346. def or_plugin_value(pluginId, key, value):
  347. global LADSPA_Plugins
  348. index = check_and_add_plugin(pluginId)
  349. LADSPA_Plugins[index][key] |= value
  350. def append_plugin_value(pluginId, key, value):
  351. global LADSPA_Plugins
  352. index = check_and_add_plugin(pluginId)
  353. LADSPA_Plugins[index][key].append(value)
  354. def check_and_add_port(pluginId, portId):
  355. global LADSPA_Plugins
  356. index = check_and_add_plugin(pluginId)
  357. ports = LADSPA_Plugins[index]['Ports']
  358. for i in range(len(ports)):
  359. if ports[i]['index'] == portId:
  360. return (index, i)
  361. else:
  362. portCount = LADSPA_Plugins[index]['PortCount']
  363. port = deepcopy(PyLADSPA_RDF_Port)
  364. port['index'] = portId
  365. ports.append(port)
  366. LADSPA_Plugins[index]['PortCount'] += 1
  367. return (index, portCount)
  368. def set_port_value(pluginId, portId, key, value):
  369. global LADSPA_Plugins
  370. i, j = check_and_add_port(pluginId, portId)
  371. LADSPA_Plugins[i]['Ports'][j][key] = value
  372. def add_port_value(pluginId, portId, key, value):
  373. global LADSPA_Plugins
  374. i, j = check_and_add_port(pluginId, portId)
  375. LADSPA_Plugins[i]['Ports'][j][key] += value
  376. def or_port_value(pluginId, portId, key, value):
  377. global LADSPA_Plugins
  378. i, j = check_and_add_port(pluginId, portId)
  379. LADSPA_Plugins[i]['Ports'][j][key] |= value
  380. def append_port_value(pluginId, portId, key, value):
  381. global LADSPA_Plugins
  382. i, j = check_and_add_port(pluginId, portId)
  383. LADSPA_Plugins[i]['Ports'][j][key].append(value)
  384. def add_scalepoint(pluginId, portId, value, label):
  385. global LADSPA_Plugins
  386. i, j = check_and_add_port(pluginId, portId)
  387. port = LADSPA_Plugins[i]['Ports'][j]
  388. scalePoint = deepcopy(PyLADSPA_RDF_ScalePoint)
  389. scalePoint['Value'] = value
  390. scalePoint['Label'] = label
  391. port['ScalePoints'].append(scalePoint)
  392. port['ScalePointCount'] += 1
  393. def set_port_default(pluginId, portId, value):
  394. global LADSPA_Plugins
  395. i, j = check_and_add_port(pluginId, portId)
  396. port = LADSPA_Plugins[i]['Ports'][j]
  397. port['Default'] = value
  398. port['Hints'] |= LADSPA_PORT_DEFAULT
  399. def get_node_objects(valueNodes, nSubject):
  400. retNodes = []
  401. for subject, predicate, object_ in valueNodes:
  402. if subject == nSubject:
  403. retNodes.append((predicate, object_))
  404. return retNodes
  405. def append_and_sort(value, vlist):
  406. if len(vlist) == 0:
  407. vlist.append(value)
  408. elif value < vlist[0]:
  409. vlist.insert(0, value)
  410. elif value > vlist[len(vlist) - 1]:
  411. vlist.append(value)
  412. else:
  413. for i in range(len(vlist)):
  414. if value < vlist[i]:
  415. vlist.insert(i, value)
  416. break
  417. else:
  418. print("LADSPA_RDF - CRITICAL ERROR #001")
  419. return vlist
  420. def get_value_index(value, vlist):
  421. for i in range(len(vlist)):
  422. if vlist[i] == value:
  423. return i
  424. else:
  425. print("LADSPA_RDF - CRITICAL ERROR #002")
  426. return 0
  427. # ------------------------------------------------------------------------------------------------------------
  428. # RDF sort data methods
  429. # Sort the plugin's port's ScalePoints by value
  430. def SORT_PyLADSPA_RDF_ScalePoints(oldDictList):
  431. newDictList = []
  432. indexesList = []
  433. for i in range(len(oldDictList)):
  434. newDictList.append(deepcopy(PyLADSPA_RDF_ScalePoint))
  435. append_and_sort(oldDictList[i]['Value'], indexesList)
  436. for i in range(len(oldDictList)):
  437. index = get_value_index(oldDictList[i]['Value'], indexesList)
  438. newDictList[index]['Value'] = oldDictList[i]['Value']
  439. newDictList[index]['Label'] = oldDictList[i]['Label']
  440. return newDictList
  441. # Sort the plugin's port by index
  442. def SORT_PyLADSPA_RDF_Ports(oldDictList):
  443. newDictList = []
  444. maxIndex = -1
  445. for i in range(len(oldDictList)):
  446. if oldDictList[i]['index'] > maxIndex:
  447. maxIndex = oldDictList[i]['index']
  448. for i in range(maxIndex + 1):
  449. newDictList.append(deepcopy(PyLADSPA_RDF_Port))
  450. for i in range(len(oldDictList)):
  451. index = oldDictList[i]['index']
  452. newDictList[index]['index'] = oldDictList[i]['index']
  453. newDictList[index]['Type'] = oldDictList[i]['Type']
  454. newDictList[index]['Hints'] = oldDictList[i]['Hints']
  455. newDictList[index]['Unit'] = oldDictList[i]['Unit']
  456. newDictList[index]['Default'] = oldDictList[i]['Default']
  457. newDictList[index]['Label'] = oldDictList[i]['Label']
  458. newDictList[index]['ScalePointCount'] = oldDictList[i]['ScalePointCount']
  459. newDictList[index]['ScalePoints'] = SORT_PyLADSPA_RDF_ScalePoints(oldDictList[i]['ScalePoints'])
  460. return newDictList
  461. # ------------------------------------------------------------------------------------------------------------
  462. # RDF data parsing
  463. from rdflib import ConjunctiveGraph, URIRef, BNode
  464. # Fully parse rdf file
  465. def parse_rdf_file(filename):
  466. primer = ConjunctiveGraph()
  467. try:
  468. primer.parse(filename, format='xml')
  469. rdfList = [(x, y, z) for x, y, z in primer]
  470. except:
  471. rdfList = []
  472. # For BNodes
  473. indexNodes = [] # Subject (index), Predicate, Plugin, Port
  474. valueNodes = [] # Subject (index), Predicate, Object
  475. # Parse RDF list
  476. for subject, predicate, object_ in rdfList:
  477. # Fix broken or old plugins
  478. if predicate == URIRef("http://ladspa.org/ontology#hasUnits"):
  479. predicate = URIRef(rdf_prefix['ladspa:hasUnit'])
  480. # Plugin information
  481. if rdf_is_type(subject, LADSPA_RDF_TYPE_PLUGIN):
  482. pluginId = int(to_plugin_number(subject))
  483. if predicate == URIRef(rdf_prefix['dc:creator']):
  484. set_plugin_value(pluginId, 'Creator', str(object_))
  485. elif predicate == URIRef(rdf_prefix['dc:rights']):
  486. # No useful information here
  487. pass
  488. elif predicate == URIRef(rdf_prefix['dc:title']):
  489. set_plugin_value(pluginId, 'Title', str(object_))
  490. elif predicate == URIRef(rdf_prefix['rdf:type']):
  491. c_type = get_c_plugin_type(str(object_))
  492. or_plugin_value(pluginId, 'Type', c_type)
  493. elif predicate == URIRef(rdf_prefix['ladspa:hasPort']):
  494. # No useful information here
  495. pass
  496. elif predicate == URIRef(rdf_prefix['ladspa:hasSetting']):
  497. indexNodes.append((object_, predicate, pluginId, None))
  498. else:
  499. print("LADSPA_RDF - Plugin predicate '%s' not handled" % predicate)
  500. # Port information
  501. elif rdf_is_type(subject, LADSPA_RDF_TYPE_PORT):
  502. portInfo = to_plugin_and_port_number(subject)
  503. pluginId = int(portInfo[0])
  504. portId = int(portInfo[1])
  505. if predicate == URIRef(rdf_prefix['rdf:type']):
  506. c_class = get_c_port_type(str(object_))
  507. or_port_value(pluginId, portId, 'Type', c_class)
  508. elif predicate == URIRef(rdf_prefix['ladspa:hasLabel']):
  509. set_port_value(pluginId, portId, 'Label', str(object_))
  510. or_port_value(pluginId, portId, 'Hints', LADSPA_PORT_LABEL)
  511. elif predicate == URIRef(rdf_prefix['ladspa:hasScale']):
  512. indexNodes.append((object_, predicate, pluginId, portId))
  513. elif predicate == URIRef(rdf_prefix['ladspa:hasUnit']):
  514. c_unit = get_c_unit_type(str(object_))
  515. set_port_value(pluginId, portId, 'Unit', c_unit)
  516. or_port_value(pluginId, portId, 'Hints', LADSPA_PORT_UNIT)
  517. else:
  518. print("LADSPA_RDF - Port predicate '%s' not handled" % predicate)
  519. # These "extensions" are already implemented. caps stuff is skipped
  520. elif subject in (URIRef(rdf_prefix['ladspa:NotchPlugin']), URIRef(rdf_prefix['ladspa:SpectralPlugin'])) or NS_caps in subject:
  521. pass
  522. elif type(subject) == BNode:
  523. valueNodes.append((subject, predicate, object_))
  524. else:
  525. print("LADSPA_RDF - Unknown subject type '%s'" % subject)
  526. # Parse BNodes, indexes
  527. bnodesDataDump = []
  528. for nSubject, nPredicate, pluginId, portId in indexNodes:
  529. nObjects = get_node_objects(valueNodes, nSubject)
  530. for subPredicate, subSubject in nObjects:
  531. subObjects = get_node_objects(valueNodes, subSubject)
  532. for realPredicate, realObject in subObjects:
  533. if nPredicate == URIRef(rdf_prefix['ladspa:hasScale']) and subPredicate == URIRef(rdf_prefix['ladspa:hasPoint']):
  534. bnodesDataDump.append(("scalepoint", subSubject, pluginId, portId, realPredicate, realObject))
  535. elif nPredicate == URIRef(rdf_prefix['ladspa:hasSetting']) and subPredicate == URIRef(rdf_prefix['ladspa:hasPortValue']):
  536. bnodesDataDump.append(("port_default", subSubject, pluginId, portId, realPredicate, realObject))
  537. else:
  538. print("LADSPA_RDF - Unknown BNode combo - '%s' + '%s'" % (nPredicate, subPredicate))
  539. # Process BNodes, values
  540. scalePoints = [] # subject, plugin, port, value, label
  541. portDefaults = [] # subject, plugin, port, def-value
  542. for nType, nSubject, nPlugin, nPort, nPredicate, nObject in bnodesDataDump:
  543. if nType == "scalepoint":
  544. for i in range(len(scalePoints)):
  545. if scalePoints[i][0] == nSubject:
  546. index = i
  547. break
  548. else:
  549. scalePoints.append([nSubject, nPlugin, nPort, None, None])
  550. index = len(scalePoints) - 1
  551. if nPredicate == URIRef(rdf_prefix['rdf:value']):
  552. scalePoints[index][3] = to_float(nObject)
  553. elif nPredicate == URIRef(rdf_prefix['ladspa:hasLabel']):
  554. scalePoints[index][4] = str(nObject)
  555. elif nType == "port_default":
  556. for i in range(len(portDefaults)):
  557. if portDefaults[i][0] == nSubject:
  558. index = i
  559. break
  560. else:
  561. portDefaults.append([nSubject, nPlugin, None, None])
  562. index = len(portDefaults) - 1
  563. if nPredicate == URIRef(rdf_prefix['ladspa:forPort']):
  564. portDefaults[index][2] = int(to_plugin_port(nObject))
  565. elif nPredicate == URIRef(rdf_prefix['rdf:value']):
  566. portDefaults[index][3] = to_float(nObject)
  567. # Now add the last information
  568. for scalePoint in scalePoints:
  569. index, pluginId, portId, value, label = scalePoint
  570. add_scalepoint(pluginId, portId, value, label)
  571. for portDefault in portDefaults:
  572. index, pluginId, portId, value = portDefault
  573. set_port_default(pluginId, portId, value)
  574. # ------------------------------------------------------------------------------------------------------------
  575. # LADSPA_RDF main methods
  576. import os
  577. # Main function - check all rdfs for information about ladspa plugins
  578. def recheck_all_plugins(qobject, startValue, percentValue, curValue):
  579. global LADSPA_RDF_PATH, LADSPA_Plugins
  580. LADSPA_Plugins = []
  581. rdfFiles = []
  582. rdfExtensions = (".rdf",)
  583. # Get all RDF files
  584. for PATH in LADSPA_RDF_PATH:
  585. for root, dirs, files in os.walk(PATH):
  586. for filename in tuple(filename for filename in files if filename.lower().endswith(rdfExtensions)):
  587. rdfFiles.append(os.path.join(root, filename))
  588. # Parse all RDF files
  589. for i in range(len(rdfFiles)):
  590. rdfFile = rdfFiles[i]
  591. # Tell GUI we're parsing this bundle
  592. if qobject:
  593. percent = (float(i) / len(rdfFiles) ) * percentValue
  594. qobject._pluginLook(startValue + (percent * curValue), rdfFile)
  595. # Parse RDF
  596. parse_rdf_file(rdfFile)
  597. return LADSPA_Plugins
  598. # Convert PyLADSPA_Plugins into ctype structs
  599. def get_c_ladspa_rdfs(pyPluginList):
  600. C_LADSPA_Plugins = []
  601. c_unicodeErrorStr = "(unicode error)".encode("utf-8")
  602. for plugin in pyPluginList:
  603. # Sort the ports by index
  604. pyLadspaPorts = SORT_PyLADSPA_RDF_Ports(plugin['Ports'])
  605. # Initial data
  606. desc = LADSPA_RDF_Descriptor()
  607. desc.Type = plugin['Type']
  608. desc.UniqueID = plugin['UniqueID']
  609. try:
  610. if plugin['Title']:
  611. desc.Title = plugin['Title'].encode("utf-8")
  612. else:
  613. desc.Title = c_nullptr
  614. except:
  615. desc.Title = c_unicodeErrorStr
  616. try:
  617. if plugin['Creator']:
  618. desc.Creator = plugin['Creator'].encode("utf-8")
  619. else:
  620. desc.Creator = c_nullptr
  621. except:
  622. desc.Creator = c_unicodeErrorStr
  623. desc.PortCount = plugin['PortCount']
  624. # Ports
  625. _PortType = LADSPA_RDF_Port * desc.PortCount
  626. desc.Ports = _PortType()
  627. for i in range(desc.PortCount):
  628. port = LADSPA_RDF_Port()
  629. pyPort = pyLadspaPorts[i]
  630. port.Type = pyPort['Type']
  631. port.Hints = pyPort['Hints']
  632. try:
  633. if pyPort['Label']:
  634. port.Label = pyPort['Label'].encode("utf-8")
  635. else:
  636. port.Label = c_nullptr
  637. except:
  638. port.Label = c_unicodeErrorStr
  639. port.Default = pyPort['Default']
  640. port.Unit = pyPort['Unit']
  641. # ScalePoints
  642. port.ScalePointCount = pyPort['ScalePointCount']
  643. _ScalePointType = LADSPA_RDF_ScalePoint * port.ScalePointCount
  644. port.ScalePoints = _ScalePointType()
  645. for j in range(port.ScalePointCount):
  646. scalePoint = LADSPA_RDF_ScalePoint()
  647. pyScalePoint = pyPort['ScalePoints'][j]
  648. try:
  649. if pyScalePoint['Label']:
  650. scalePoint.Label = pyScalePoint['Label'].encode("utf-8")
  651. else:
  652. scalePoint.Label = c_nullptr
  653. except:
  654. scalePoint.Label = c_unicodeErrorStr
  655. scalePoint.Value = pyScalePoint['Value']
  656. port.ScalePoints[j] = scalePoint
  657. desc.Ports[i] = port
  658. C_LADSPA_Plugins.append(desc)
  659. return C_LADSPA_Plugins
  660. # ------------------------------------------------------------------------------------------------------------