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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  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. # ------------------------------------------------------------------------------------------------------------