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
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  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