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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  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 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. # Prefixes (sorted alphabetically and by type)
  150. rdf_prefix = {
  151. # Base types
  152. 'dc:creator': NS_dc + "creator",
  153. 'dc:rights': NS_dc + "rights",
  154. 'dc:title': NS_dc + "title",
  155. 'rdf:value': NS_rdf + "value",
  156. 'rdf:type': NS_rdf + "type",
  157. # LADSPA Stuff
  158. 'ladspa:forPort': NS_ladspa + "forPort",
  159. 'ladspa:hasLabel': NS_ladspa + "hasLabel",
  160. 'ladspa:hasPoint': NS_ladspa + "hasPoint",
  161. 'ladspa:hasPort': NS_ladspa + "hasPort",
  162. 'ladspa:hasPortValue': NS_ladspa + "hasPortValue",
  163. 'ladspa:hasScale': NS_ladspa + "hasScale",
  164. 'ladspa:hasSetting': NS_ladspa + "hasSetting",
  165. 'ladspa:hasUnit': NS_ladspa + "hasUnit",
  166. # LADSPA Extensions
  167. 'ladspa:NotchPlugin': NS_ladspa + "NotchPlugin",
  168. 'ladspa:SpectralPlugin': NS_ladspa + "SpectralPlugin"
  169. }
  170. def get_c_plugin_type(value):
  171. valueStr = value.replace(NS_ladspa, "")
  172. ret = 0x0
  173. if valueStr == "Plugin":
  174. pass
  175. elif valueStr == "UtilityPlugin":
  176. ret = LADSPA_PLUGIN_UTILITY
  177. elif valueStr == "GeneratorPlugin":
  178. ret = LADSPA_PLUGIN_GENERATOR
  179. elif valueStr == "SimulatorPlugin":
  180. ret = LADSPA_PLUGIN_SIMULATOR
  181. elif valueStr == "OscillatorPlugin":
  182. ret = LADSPA_PLUGIN_OSCILLATOR
  183. elif valueStr == "TimePlugin":
  184. ret = LADSPA_PLUGIN_TIME
  185. elif valueStr == "DelayPlugin":
  186. ret = LADSPA_PLUGIN_DELAY
  187. elif valueStr == "PhaserPlugin":
  188. ret = LADSPA_PLUGIN_PHASER
  189. elif valueStr == "FlangerPlugin":
  190. ret = LADSPA_PLUGIN_FLANGER
  191. elif valueStr == "ChorusPlugin":
  192. ret = LADSPA_PLUGIN_CHORUS
  193. elif valueStr == "ReverbPlugin":
  194. ret = LADSPA_PLUGIN_REVERB
  195. elif valueStr == "FrequencyPlugin":
  196. ret = LADSPA_PLUGIN_FREQUENCY
  197. elif valueStr == "FrequencyMeterPlugin":
  198. ret = LADSPA_PLUGIN_FREQUENCY_METER
  199. elif valueStr == "FilterPlugin":
  200. ret = LADSPA_PLUGIN_FILTER
  201. elif valueStr == "LowpassPlugin":
  202. ret = LADSPA_PLUGIN_LOWPASS
  203. elif valueStr == "HighpassPlugin":
  204. ret = LADSPA_PLUGIN_HIGHPASS
  205. elif valueStr == "BandpassPlugin":
  206. ret = LADSPA_PLUGIN_BANDPASS
  207. elif valueStr == "CombPlugin":
  208. ret = LADSPA_PLUGIN_COMB
  209. elif valueStr == "AllpassPlugin":
  210. ret = LADSPA_PLUGIN_ALLPASS
  211. elif valueStr == "EQPlugin":
  212. ret = LADSPA_PLUGIN_EQ
  213. elif valueStr == "ParaEQPlugin":
  214. ret = LADSPA_PLUGIN_PARAEQ
  215. elif valueStr == "MultiEQPlugin":
  216. ret = LADSPA_PLUGIN_MULTIEQ
  217. elif valueStr == "AmplitudePlugin":
  218. ret = LADSPA_PLUGIN_AMPLITUDE
  219. elif valueStr == "PitchPlugin":
  220. ret = LADSPA_PLUGIN_PITCH
  221. elif valueStr == "AmplifierPlugin":
  222. ret = LADSPA_PLUGIN_AMPLIFIER
  223. elif valueStr == "WaveshaperPlugin":
  224. ret = LADSPA_PLUGIN_WAVESHAPER
  225. elif valueStr == "ModulatorPlugin":
  226. ret = LADSPA_PLUGIN_MODULATOR
  227. elif valueStr == "DistortionPlugin":
  228. ret = LADSPA_PLUGIN_DISTORTION
  229. elif valueStr == "DynamicsPlugin":
  230. ret = LADSPA_PLUGIN_DYNAMICS
  231. elif valueStr == "CompressorPlugin":
  232. ret = LADSPA_PLUGIN_COMPRESSOR
  233. elif valueStr == "ExpanderPlugin":
  234. ret = LADSPA_PLUGIN_EXPANDER
  235. elif valueStr == "LimiterPlugin":
  236. ret = LADSPA_PLUGIN_LIMITER
  237. elif valueStr == "GatePlugin":
  238. ret = LADSPA_PLUGIN_GATE
  239. elif valueStr == "SpectralPlugin":
  240. ret = LADSPA_PLUGIN_SPECTRAL
  241. elif valueStr == "NotchPlugin":
  242. ret = LADSPA_PLUGIN_NOTCH
  243. elif valueStr == "MixerPlugin":
  244. ret = LADSPA_PLUGIN_EQ
  245. else:
  246. print("LADSPA_RDF - Got an unknown plugin type '%s'" % valueStr)
  247. return ret
  248. def get_c_port_type(value):
  249. valueStr = value.replace(NS_ladspa, "")
  250. ret = 0x0
  251. if valueStr == "Port":
  252. pass
  253. elif valueStr == "ControlPort":
  254. ret = LADSPA_PORT_CONTROL
  255. elif valueStr == "AudioPort":
  256. ret = LADSPA_PORT_AUDIO
  257. elif valueStr == "InputPort":
  258. ret = LADSPA_PORT_INPUT
  259. elif valueStr == "OutputPort":
  260. ret = LADSPA_PORT_OUTPUT
  261. elif valueStr in ("ControlInputPort", "InputControlPort"):
  262. ret = LADSPA_PORT_CONTROL|LADSPA_PORT_INPUT
  263. elif valueStr in ("ControlOutputPort", "OutputControlPort"):
  264. ret = LADSPA_PORT_CONTROL|LADSPA_PORT_OUTPUT
  265. elif valueStr in ("AudioInputPort", "InputAudioPort"):
  266. ret = LADSPA_PORT_AUDIO|LADSPA_PORT_INPUT
  267. elif valueStr in ("AudioOutputPort", "OutputAudioPort"):
  268. ret = LADSPA_PORT_AUDIO|LADSPA_PORT_OUTPUT
  269. else:
  270. print("LADSPA_RDF - Got an unknown port type '%s'" % valueStr)
  271. return ret
  272. def get_c_unit_type(value):
  273. valueStr = value.replace(NS_ladspa, "")
  274. ret = 0x0
  275. if valueStr in ("Unit", "Units", "AmplitudeUnits", "FrequencyUnits", "TimeUnits"):
  276. pass
  277. elif valueStr == "dB":
  278. ret = LADSPA_UNIT_DB
  279. elif valueStr == "coef":
  280. ret = LADSPA_UNIT_COEF
  281. elif valueStr == "Hz":
  282. ret = LADSPA_UNIT_HZ
  283. elif valueStr == "seconds":
  284. ret = LADSPA_UNIT_S
  285. elif valueStr == "milliseconds":
  286. ret = LADSPA_UNIT_MS
  287. elif valueStr == "minutes":
  288. ret = LADSPA_UNIT_MIN
  289. else:
  290. print("LADSPA_RDF - Got an unknown unit type '%s'" % valueStr)
  291. return ret
  292. # -------------------------------------------------------------------------------
  293. # Global objects
  294. global LADSPA_RDF_PATH, LADSPA_Plugins
  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
  520. elif subject in (URIRef(rdf_prefix['ladspa:NotchPlugin']), URIRef(rdf_prefix['ladspa:SpectralPlugin'])):
  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 [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