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.

ladspa_rdf.py 27KB

12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  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. global LADSPA_RDF_PATH, LADSPA_Plugins
  296. LADSPA_RDF_PATH = ("/usr/share/ladspa/rdf", "/usr/local/share/ladspa/rdf")
  297. LADSPA_Plugins = []
  298. # Set LADSPA_RDF_PATH variable
  299. def set_rdf_path(PATH):
  300. global LADSPA_RDF_PATH
  301. LADSPA_RDF_PATH = PATH
  302. # ------------------------------------------------------------------------------------------------------------
  303. # Helper methods
  304. LADSPA_RDF_TYPE_PLUGIN = 1
  305. LADSPA_RDF_TYPE_PORT = 2
  306. # Check RDF Type
  307. def rdf_is_type(subject, compare):
  308. if isinstance(subject, URIRef) and NS_ladspa in subject:
  309. if compare == LADSPA_RDF_TYPE_PLUGIN:
  310. return bool(to_plugin_number(subject).isdigit())
  311. elif compare == LADSPA_RDF_TYPE_PORT:
  312. return bool("." in to_plugin_number(subject))
  313. else:
  314. return False
  315. def to_float(rdfItem):
  316. return float(str(rdfItem).replace("f", ""))
  317. # Convert RDF LADSPA subject into a number
  318. def to_plugin_number(subject):
  319. return str(subject).replace(NS_ladspa, "")
  320. # Convert RDF LADSPA subject into a plugin and port number
  321. def to_plugin_and_port_number(subject):
  322. numbers = str(subject).replace(NS_ladspa, "").split(".")
  323. return (numbers[0], numbers[1])
  324. # Convert RDF LADSPA subject into a port number
  325. def to_plugin_port(subject):
  326. return to_plugin_and_port_number(subject)[1]
  327. # ------------------------------------------------------------------------------------------------------------
  328. # RDF store/retrieve data methods
  329. def check_and_add_plugin(pluginId):
  330. global LADSPA_Plugins
  331. for i in range(len(LADSPA_Plugins)):
  332. if LADSPA_Plugins[i]['UniqueID'] == pluginId:
  333. return i
  334. else:
  335. plugin = deepcopy(PyLADSPA_RDF_Descriptor)
  336. plugin['UniqueID'] = pluginId
  337. LADSPA_Plugins.append(plugin)
  338. return len(LADSPA_Plugins) - 1
  339. def set_plugin_value(pluginId, key, value):
  340. global LADSPA_Plugins
  341. index = check_and_add_plugin(pluginId)
  342. LADSPA_Plugins[index][key] = value
  343. def add_plugin_value(pluginId, key, value):
  344. global LADSPA_Plugins
  345. index = check_and_add_plugin(pluginId)
  346. LADSPA_Plugins[index][key] += value
  347. def or_plugin_value(pluginId, key, value):
  348. global LADSPA_Plugins
  349. index = check_and_add_plugin(pluginId)
  350. LADSPA_Plugins[index][key] |= value
  351. def append_plugin_value(pluginId, key, value):
  352. global LADSPA_Plugins
  353. index = check_and_add_plugin(pluginId)
  354. LADSPA_Plugins[index][key].append(value)
  355. def check_and_add_port(pluginId, portId):
  356. global LADSPA_Plugins
  357. index = check_and_add_plugin(pluginId)
  358. ports = LADSPA_Plugins[index]['Ports']
  359. for i in range(len(ports)):
  360. if ports[i]['index'] == portId:
  361. return (index, i)
  362. else:
  363. portCount = LADSPA_Plugins[index]['PortCount']
  364. port = deepcopy(PyLADSPA_RDF_Port)
  365. port['index'] = portId
  366. ports.append(port)
  367. LADSPA_Plugins[index]['PortCount'] += 1
  368. return (index, portCount)
  369. def set_port_value(pluginId, portId, key, value):
  370. global LADSPA_Plugins
  371. i, j = check_and_add_port(pluginId, portId)
  372. LADSPA_Plugins[i]['Ports'][j][key] = value
  373. def add_port_value(pluginId, portId, key, value):
  374. global LADSPA_Plugins
  375. i, j = check_and_add_port(pluginId, portId)
  376. LADSPA_Plugins[i]['Ports'][j][key] += value
  377. def or_port_value(pluginId, portId, key, value):
  378. global LADSPA_Plugins
  379. i, j = check_and_add_port(pluginId, portId)
  380. LADSPA_Plugins[i]['Ports'][j][key] |= value
  381. def append_port_value(pluginId, portId, key, value):
  382. global LADSPA_Plugins
  383. i, j = check_and_add_port(pluginId, portId)
  384. LADSPA_Plugins[i]['Ports'][j][key].append(value)
  385. def add_scalepoint(pluginId, portId, value, label):
  386. global LADSPA_Plugins
  387. i, j = check_and_add_port(pluginId, portId)
  388. port = LADSPA_Plugins[i]['Ports'][j]
  389. scalePoint = deepcopy(PyLADSPA_RDF_ScalePoint)
  390. scalePoint['Value'] = value
  391. scalePoint['Label'] = label
  392. port['ScalePoints'].append(scalePoint)
  393. port['ScalePointCount'] += 1
  394. def set_port_default(pluginId, portId, value):
  395. global LADSPA_Plugins
  396. i, j = check_and_add_port(pluginId, portId)
  397. port = LADSPA_Plugins[i]['Ports'][j]
  398. port['Default'] = value
  399. port['Hints'] |= LADSPA_PORT_DEFAULT
  400. def get_node_objects(valueNodes, nSubject):
  401. retNodes = []
  402. for subject, predicate, object_ in valueNodes:
  403. if subject == nSubject:
  404. retNodes.append((predicate, object_))
  405. return retNodes
  406. def append_and_sort(value, vlist):
  407. if len(vlist) == 0:
  408. vlist.append(value)
  409. elif value < vlist[0]:
  410. vlist.insert(0, value)
  411. elif value > vlist[len(vlist) - 1]:
  412. vlist.append(value)
  413. else:
  414. for i in range(len(vlist)):
  415. if value < vlist[i]:
  416. vlist.insert(i, value)
  417. break
  418. else:
  419. print("LADSPA_RDF - CRITICAL ERROR #001")
  420. return vlist
  421. def get_value_index(value, vlist):
  422. for i in range(len(vlist)):
  423. if vlist[i] == value:
  424. return i
  425. else:
  426. print("LADSPA_RDF - CRITICAL ERROR #002")
  427. return 0
  428. # ------------------------------------------------------------------------------------------------------------
  429. # RDF sort data methods
  430. # Sort the plugin's port's ScalePoints by value
  431. def SORT_PyLADSPA_RDF_ScalePoints(oldDictList):
  432. newDictList = []
  433. indexesList = []
  434. for i in range(len(oldDictList)):
  435. newDictList.append(deepcopy(PyLADSPA_RDF_ScalePoint))
  436. append_and_sort(oldDictList[i]['Value'], indexesList)
  437. for i in range(len(oldDictList)):
  438. index = get_value_index(oldDictList[i]['Value'], indexesList)
  439. newDictList[index]['Value'] = oldDictList[i]['Value']
  440. newDictList[index]['Label'] = oldDictList[i]['Label']
  441. return newDictList
  442. # Sort the plugin's port by index
  443. def SORT_PyLADSPA_RDF_Ports(oldDictList):
  444. newDictList = []
  445. maxIndex = -1
  446. for i in range(len(oldDictList)):
  447. if oldDictList[i]['index'] > maxIndex:
  448. maxIndex = oldDictList[i]['index']
  449. for i in range(maxIndex + 1):
  450. newDictList.append(deepcopy(PyLADSPA_RDF_Port))
  451. for i in range(len(oldDictList)):
  452. index = oldDictList[i]['index']
  453. newDictList[index]['index'] = oldDictList[i]['index']
  454. newDictList[index]['Type'] = oldDictList[i]['Type']
  455. newDictList[index]['Hints'] = oldDictList[i]['Hints']
  456. newDictList[index]['Unit'] = oldDictList[i]['Unit']
  457. newDictList[index]['Default'] = oldDictList[i]['Default']
  458. newDictList[index]['Label'] = oldDictList[i]['Label']
  459. newDictList[index]['ScalePointCount'] = oldDictList[i]['ScalePointCount']
  460. newDictList[index]['ScalePoints'] = SORT_PyLADSPA_RDF_ScalePoints(oldDictList[i]['ScalePoints'])
  461. return newDictList
  462. # ------------------------------------------------------------------------------------------------------------
  463. # RDF data parsing
  464. from rdflib import ConjunctiveGraph, URIRef, BNode
  465. # Fully parse rdf file
  466. def parse_rdf_file(filename):
  467. primer = ConjunctiveGraph()
  468. try:
  469. primer.parse(filename, format='xml')
  470. rdfList = [(x, y, z) for x, y, z in primer]
  471. except:
  472. rdfList = []
  473. # For BNodes
  474. indexNodes = [] # Subject (index), Predicate, Plugin, Port
  475. valueNodes = [] # Subject (index), Predicate, Object
  476. # Parse RDF list
  477. for subject, predicate, object_ in rdfList:
  478. # Fix broken or old plugins
  479. if predicate == URIRef("http://ladspa.org/ontology#hasUnits"):
  480. predicate = URIRef(rdf_prefix['ladspa:hasUnit'])
  481. # Plugin information
  482. if rdf_is_type(subject, LADSPA_RDF_TYPE_PLUGIN):
  483. pluginId = int(to_plugin_number(subject))
  484. if predicate == URIRef(rdf_prefix['dc:creator']):
  485. set_plugin_value(pluginId, 'Creator', str(object_))
  486. elif predicate == URIRef(rdf_prefix['dc:rights']):
  487. # No useful information here
  488. pass
  489. elif predicate == URIRef(rdf_prefix['dc:title']):
  490. set_plugin_value(pluginId, 'Title', str(object_))
  491. elif predicate == URIRef(rdf_prefix['rdf:type']):
  492. c_type = get_c_plugin_type(str(object_))
  493. or_plugin_value(pluginId, 'Type', c_type)
  494. elif predicate == URIRef(rdf_prefix['ladspa:hasPort']):
  495. # No useful information here
  496. pass
  497. elif predicate == URIRef(rdf_prefix['ladspa:hasSetting']):
  498. indexNodes.append((object_, predicate, pluginId, None))
  499. else:
  500. print("LADSPA_RDF - Plugin predicate '%s' not handled" % predicate)
  501. # Port information
  502. elif rdf_is_type(subject, LADSPA_RDF_TYPE_PORT):
  503. portInfo = to_plugin_and_port_number(subject)
  504. pluginId = int(portInfo[0])
  505. portId = int(portInfo[1])
  506. if predicate == URIRef(rdf_prefix['rdf:type']):
  507. c_class = get_c_port_type(str(object_))
  508. or_port_value(pluginId, portId, 'Type', c_class)
  509. elif predicate == URIRef(rdf_prefix['ladspa:hasLabel']):
  510. set_port_value(pluginId, portId, 'Label', str(object_))
  511. or_port_value(pluginId, portId, 'Hints', LADSPA_PORT_LABEL)
  512. elif predicate == URIRef(rdf_prefix['ladspa:hasScale']):
  513. indexNodes.append((object_, predicate, pluginId, portId))
  514. elif predicate == URIRef(rdf_prefix['ladspa:hasUnit']):
  515. c_unit = get_c_unit_type(str(object_))
  516. set_port_value(pluginId, portId, 'Unit', c_unit)
  517. or_port_value(pluginId, portId, 'Hints', LADSPA_PORT_UNIT)
  518. else:
  519. print("LADSPA_RDF - Port predicate '%s' not handled" % predicate)
  520. # These "extensions" are already implemented. caps stuff is skipped
  521. elif subject in (URIRef(rdf_prefix['ladspa:NotchPlugin']), URIRef(rdf_prefix['ladspa:SpectralPlugin'])) or NS_caps in subject:
  522. pass
  523. elif type(subject) == BNode:
  524. valueNodes.append((subject, predicate, object_))
  525. else:
  526. print("LADSPA_RDF - Unknown subject type '%s'" % subject)
  527. # Parse BNodes, indexes
  528. bnodesDataDump = []
  529. for nSubject, nPredicate, pluginId, portId in indexNodes:
  530. nObjects = get_node_objects(valueNodes, nSubject)
  531. for subPredicate, subSubject in nObjects:
  532. subObjects = get_node_objects(valueNodes, subSubject)
  533. for realPredicate, realObject in subObjects:
  534. if nPredicate == URIRef(rdf_prefix['ladspa:hasScale']) and subPredicate == URIRef(rdf_prefix['ladspa:hasPoint']):
  535. bnodesDataDump.append(("scalepoint", subSubject, pluginId, portId, realPredicate, realObject))
  536. elif nPredicate == URIRef(rdf_prefix['ladspa:hasSetting']) and subPredicate == URIRef(rdf_prefix['ladspa:hasPortValue']):
  537. bnodesDataDump.append(("port_default", subSubject, pluginId, portId, realPredicate, realObject))
  538. else:
  539. print("LADSPA_RDF - Unknown BNode combo - '%s' + '%s'" % (nPredicate, subPredicate))
  540. # Process BNodes, values
  541. scalePoints = [] # subject, plugin, port, value, label
  542. portDefaults = [] # subject, plugin, port, def-value
  543. for nType, nSubject, nPlugin, nPort, nPredicate, nObject in bnodesDataDump:
  544. if nType == "scalepoint":
  545. for i in range(len(scalePoints)):
  546. if scalePoints[i][0] == nSubject:
  547. index = i
  548. break
  549. else:
  550. scalePoints.append([nSubject, nPlugin, nPort, None, None])
  551. index = len(scalePoints) - 1
  552. if nPredicate == URIRef(rdf_prefix['rdf:value']):
  553. scalePoints[index][3] = to_float(nObject)
  554. elif nPredicate == URIRef(rdf_prefix['ladspa:hasLabel']):
  555. scalePoints[index][4] = str(nObject)
  556. elif nType == "port_default":
  557. for i in range(len(portDefaults)):
  558. if portDefaults[i][0] == nSubject:
  559. index = i
  560. break
  561. else:
  562. portDefaults.append([nSubject, nPlugin, None, None])
  563. index = len(portDefaults) - 1
  564. if nPredicate == URIRef(rdf_prefix['ladspa:forPort']):
  565. portDefaults[index][2] = int(to_plugin_port(nObject))
  566. elif nPredicate == URIRef(rdf_prefix['rdf:value']):
  567. portDefaults[index][3] = to_float(nObject)
  568. # Now add the last information
  569. for scalePoint in scalePoints:
  570. index, pluginId, portId, value, label = scalePoint
  571. add_scalepoint(pluginId, portId, value, label)
  572. for portDefault in portDefaults:
  573. index, pluginId, portId, value = portDefault
  574. set_port_default(pluginId, portId, value)
  575. # ------------------------------------------------------------------------------------------------------------
  576. # LADSPA_RDF main methods
  577. import os
  578. # Main function - check all rdfs for information about ladspa plugins
  579. def recheck_all_plugins(qobject, startValue, percentValue, curValue):
  580. global LADSPA_RDF_PATH, LADSPA_Plugins
  581. LADSPA_Plugins = []
  582. rdfFiles = []
  583. rdfExtensions = (".rdf",)
  584. # Get all RDF files
  585. for PATH in LADSPA_RDF_PATH:
  586. for root, dirs, files in os.walk(PATH):
  587. for filename in [filename for filename in files if filename.lower().endswith(rdfExtensions)]:
  588. rdfFiles.append(os.path.join(root, filename))
  589. # Parse all RDF files
  590. for i in range(len(rdfFiles)):
  591. rdfFile = rdfFiles[i]
  592. # Tell GUI we're parsing this bundle
  593. if qobject:
  594. percent = (float(i) / len(rdfFiles) ) * percentValue
  595. qobject._pluginLook(startValue + (percent * curValue), rdfFile)
  596. # Parse RDF
  597. parse_rdf_file(rdfFile)
  598. return LADSPA_Plugins
  599. # Convert PyLADSPA_Plugins into ctype structs
  600. def get_c_ladspa_rdfs(pyPluginList):
  601. C_LADSPA_Plugins = []
  602. c_unicodeErrorStr = "(unicode error)".encode("utf-8")
  603. for plugin in pyPluginList:
  604. # Sort the ports by index
  605. pyLadspaPorts = SORT_PyLADSPA_RDF_Ports(plugin['Ports'])
  606. # Initial data
  607. desc = LADSPA_RDF_Descriptor()
  608. desc.Type = plugin['Type']
  609. desc.UniqueID = plugin['UniqueID']
  610. try:
  611. if plugin['Title']:
  612. desc.Title = plugin['Title'].encode("utf-8")
  613. else:
  614. desc.Title = c_nullptr
  615. except:
  616. desc.Title = c_unicodeErrorStr
  617. try:
  618. if plugin['Creator']:
  619. desc.Creator = plugin['Creator'].encode("utf-8")
  620. else:
  621. desc.Creator = c_nullptr
  622. except:
  623. desc.Creator = c_unicodeErrorStr
  624. desc.PortCount = plugin['PortCount']
  625. # Ports
  626. _PortType = LADSPA_RDF_Port * desc.PortCount
  627. desc.Ports = _PortType()
  628. for i in range(desc.PortCount):
  629. port = LADSPA_RDF_Port()
  630. pyPort = pyLadspaPorts[i]
  631. port.Type = pyPort['Type']
  632. port.Hints = pyPort['Hints']
  633. try:
  634. if pyPort['Label']:
  635. port.Label = pyPort['Label'].encode("utf-8")
  636. else:
  637. port.Label = c_nullptr
  638. except:
  639. port.Label = c_unicodeErrorStr
  640. port.Default = pyPort['Default']
  641. port.Unit = pyPort['Unit']
  642. # ScalePoints
  643. port.ScalePointCount = pyPort['ScalePointCount']
  644. _ScalePointType = LADSPA_RDF_ScalePoint * port.ScalePointCount
  645. port.ScalePoints = _ScalePointType()
  646. for j in range(port.ScalePointCount):
  647. scalePoint = LADSPA_RDF_ScalePoint()
  648. pyScalePoint = pyPort['ScalePoints'][j]
  649. try:
  650. if pyScalePoint['Label']:
  651. scalePoint.Label = pyScalePoint['Label'].encode("utf-8")
  652. else:
  653. scalePoint.Label = c_nullptr
  654. except:
  655. scalePoint.Label = c_unicodeErrorStr
  656. scalePoint.Value = pyScalePoint['Value']
  657. port.ScalePoints[j] = scalePoint
  658. desc.Ports[i] = port
  659. C_LADSPA_Plugins.append(desc)
  660. return C_LADSPA_Plugins
  661. # ------------------------------------------------------------------------------------------------------------